[rdkb][common][bsp][Refactor and sync kernel from openwrt]
[Description]
920ddcf2 [MAC80211][hnat][Update IPv6 unbind issue for the routing mode]
937ac411 [kernel][common][Update kernel config to prevent build stop]
3d4ced59 [kernel][common][eth][Add netdev_upper_dev_link feature to the dsa_slave_create() function]
5a77ee07 [kernel][common][eth][Add dsa_port_from_netdev API to dsa framework]
ffb7812c [kernel][common][leds][Update kernel config to prevent build stop]
1f4d9d3a [openwrt][common][Add test tool to pass test vector]
5e041364 [openwrt][common][Change package category in menuconfig]
81974696 [openwrt][common][Fix aes ccm mode encrypt bug]
28b6a279 [openwrt][common][Fix build error in openssl-fips-ext]
769c7697 [kernel][common][Add patch to achieve fips140-3 compliance]
9b59f267 [openwrt][common][Add libkcapi to test fips140-3]
46bf5245 [openwrt][common][Add jitterrng package]
bf6fe74a [kernel][common][Backport libkcapi to v5.10]
8ad792d1 [kernel][common][Backport jitterrng to 2.2.0]
13ee647a [MAC80211][hnat][Fix IPv6 unbind issue for the routing mode]
05856c54 [kernel][mt7988][eth][Add 10G WAN support to mt7988d base on dsa-10g-spim-nand DTS]
313f5766 [openwrt][mt7988][tops][remove script 98-mtk-vpn]
4605625c [openwrt][mt7988][tops][support v1.2.0]
02a32c90 [openwrt][common][audio][Remove obsolete mt79xx audio driver from module.mk]
33b9a8df [openwrt][common][audio][Add WM8960 codec and MT7986 audio drivers to sound.mk]
7583e3a7 [kernel][mt7988][eth][Fix Link Partner link down issue for the SFP+ optical module]
259d232d [MAC80211][WED][Fix MT7981 wed detach occur call trace issue]
38b67904 [openwrt][mt7988][crypto][Refactor FP setting in IPSec hnat binding flow]
29f07a46 [openwrt][mt7988][crypto][Add check for algorithm used in xfrm_state]
68a3a4d8 [MAC80211][WED][Fix 2G WMM test fail]
f4a9a9af [kernel][common][leds][Add backport leds pwm multicolor from kernel 6.4]
86e8737c [kernel][mt7988][eth][Add DIP dynamic allocation to the LRO]
5433dd92 [kernel][mt7988][eth][i2.5Gphy: Add safer sequence to loadfirmware]
57514f1b [kernel][common][Refactor pinctrl spinlock patch name]
9a1a5b6c [kernel][pinctrl][Rename backport pinctrl patch]
2a50af6c [kernel][mt7988][crypto][Change backport patch name to satisfy naming rule]
dbbaf2d8 [openwrt][mt7988][tops][support v1.1.0]
a8235047 [kernel][common][eth][Fix refcount underflow issue in the pending_work]
ed7846eb [MAC80211][hnat][Improve ETH to ETH performace in an unbalanced PHY rate test for the mt7988]
30b53d1f [kernel][mt7988][hnat][Fix issue with 3PPE HNAT BIND during LAN WAN role swap]
5b4aef62 [kernel][mt7988][crypto][Fix xfrm_state add to hashtable]
8eefe83b [kernel][mt7988][hnat][Correct maximum rate limit criteria for the qdma_txqX and qdma_schX commands]
69a4f5af [kernel][mt7986][hnat][Fix issue of inactive HQoS functionality under PPPQ mode]
7a74acf7 [openwrt][common][Upgrade kernel version from 5.4.246 to 5.4.260]
1345887d [openwrt][common][crypto][Add kmod-crypto-chacha20-poly1305]
1404373a [kernel][common][Refactor rtq6056 backport patch path]
62742395 [openwrt][mt7988][pce][fix coverity defects]
ce4a3c4a [kernel][common][Refactor dhrystone backport patch path]
7fa2cbf9 [kernel][common][audio][Refactor mt7986 audio driver backport patch path]
026e4289 [MAC80211][hnat][Fix 64B short packets test cannot reach line rate for the mt7988]
3a75d682 [kernel][mt7988][crypto][Change xfrm policy check for IPsec decryption path]
eb84c73c [kernel][common][eth][Fix issue with XGDM hang when reconnecting SFP+ Optical module]
ac5fc068 [openwrt][mt7988][pce][fix out-of-bound array access]
97385f3c [kernel][common][eth][Fix issue with late-col hang when operating in half-duplex on the SGMII 1G PHY]
06f8dfe6 [MAC80211][hnat][Fix the typo to enable caching of the MIB function]
6b4b77e7 [kernel][common][audio][Add mt7986 audio driver in dts files]
34d90265 [kernel][common][audio][Add mt7986proslic machine driver to Kconfig and Makefile]
6f715d67 [kernel][common][audio][Add mt7986proslic machine driver]
b8c2e923 [kernel][common][audio][Add backport mt7986 audio driver from kernel 6.7]
2f1abd04 [kernel][common][audio][Remove mt79xx audio driver]
98e9ba78 [kernel][common][eth][Fix a traffic stuck issue when changing the SGMII autoneg mode]
0b6f8d87 [MAC80211][hnat][Add multiple PPE allocation of the ETH for mt7988]
162c66eb [openwrt][common][crypto][Remove ipsec service in strongswan]
8669e93b [openwrt][common][crypto][Change strongswan package dependency]
0c532b0d [kernel][mt7988][hnat][Add support for preventing hardware acceleration via skb mark checking]
7967721e [openwrt][mt7988][audio][Add -spi and driver to Kconfig and Makefile]
42c9b50b [openwrt][mt7988][audio][Add -spi for slic driver test]
8fe39e57 [openwrt][mt7988][crypto][Fix compile error without hnat]
[Release-log]
Change-Id: Ic979c02edfaccd00ea95b478ca0113a3434b4987
diff --git a/recipes-bsp/mediatek-eth-firmware/files/mediatek-2p5ge-phy-pmb.bin b/recipes-bsp/mediatek-eth-firmware/files/i2p5ge-phy-pmb.bin
similarity index 100%
rename from recipes-bsp/mediatek-eth-firmware/files/mediatek-2p5ge-phy-pmb.bin
rename to recipes-bsp/mediatek-eth-firmware/files/i2p5ge-phy-pmb.bin
Binary files differ
diff --git a/recipes-bsp/mediatek-eth-firmware/files/mediatek-2p5ge-phy-dmb.bin b/recipes-bsp/mediatek-eth-firmware/files/mediatek-2p5ge-phy-dmb.bin
deleted file mode 100644
index 12f3be4..0000000
--- a/recipes-bsp/mediatek-eth-firmware/files/mediatek-2p5ge-phy-dmb.bin
+++ /dev/null
Binary files differ
diff --git a/recipes-bsp/mediatek-eth-firmware/mediatek-eth-firmware.bb b/recipes-bsp/mediatek-eth-firmware/mediatek-eth-firmware.bb
index 8962af2..d8ccad1 100644
--- a/recipes-bsp/mediatek-eth-firmware/mediatek-eth-firmware.bb
+++ b/recipes-bsp/mediatek-eth-firmware/mediatek-eth-firmware.bb
@@ -4,20 +4,18 @@
LICENSE = "CLOSED"
SRC_URI = " \
- file://mediatek-2p5ge-phy-dmb.bin \
- file://mediatek-2p5ge-phy-pmb.bin \
+ file://i2p5ge-phy-pmb.bin \
"
S = "${WORKDIR}"
inherit allarch
do_install() {
- install -d ${D}/${base_libdir}/firmware/
- install -m 644 ${WORKDIR}/mediatek-2p5ge-phy-dmb.bin ${D}${base_libdir}/firmware/
- install -m 644 ${WORKDIR}/mediatek-2p5ge-phy-pmb.bin ${D}${base_libdir}/firmware/
+ install -d ${D}/${base_libdir}/firmware/mediatek/mt7988/
+ install -m 644 ${WORKDIR}/i2p5ge-phy-pmb.bin ${D}${base_libdir}/firmware/mediatek/mt7988/
}
-FILES_${PN} += "${base_libdir}/firmware/*"
+FILES_${PN} += "${base_libdir}/firmware/mediatek/mt7988/*"
# Make Mediatek-eth-firmware depend on all of the split-out packages.
python populate_packages_prepend () {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/711-v6.3-bgmac-fix-initial-chip-reset-to-support-BCM5358.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/711-v6.3-bgmac-fix-initial-chip-reset-to-support-BCM5358.patch
deleted file mode 100644
index 54f077b..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/711-v6.3-bgmac-fix-initial-chip-reset-to-support-BCM5358.patch
+++ /dev/null
@@ -1,76 +0,0 @@
-From 327dabbd0111910a7d174b0b812d608d6b67bead Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Mon, 8 Aug 2022 23:05:25 +0200
-Subject: [PATCH] bgmac: fix *initial* chip reset to support BCM5358
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-While bringing hardware up we should perform a full reset including the
-switch bit (BGMAC_BCMA_IOCTL_SW_RESET aka SICF_SWRST). It's what
-specification says and what reference driver does.
-
-This seems to be critical for the BCM5358. Without this hardware doesn't
-get initialized properly and doesn't seem to transmit or receive any
-packets.
-
-Originally bgmac was calling bgmac_chip_reset() before setting
-"has_robosw" property which resulted in expected behaviour. That has
-changed as a side effect of adding platform device support which
-regressed BCM5358 support.
-
-Fixes: f6a95a24957a ("net: ethernet: bgmac: Add platform device support")
-Cc: Jon Mason <jdmason@kudzu.us>
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
----
- drivers/net/ethernet/broadcom/bgmac.c | 8 ++++++--
- drivers/net/ethernet/broadcom/bgmac.h | 2 ++
- 2 files changed, 8 insertions(+), 2 deletions(-)
-
---- a/drivers/net/ethernet/broadcom/bgmac.c
-+++ b/drivers/net/ethernet/broadcom/bgmac.c
-@@ -890,13 +890,13 @@ static void bgmac_chip_reset_idm_config(
-
- if (iost & BGMAC_BCMA_IOST_ATTACHED) {
- flags = BGMAC_BCMA_IOCTL_SW_CLKEN;
-- if (!bgmac->has_robosw)
-+ if (bgmac->in_init || !bgmac->has_robosw)
- flags |= BGMAC_BCMA_IOCTL_SW_RESET;
- }
- bgmac_clk_enable(bgmac, flags);
- }
-
-- if (iost & BGMAC_BCMA_IOST_ATTACHED && !bgmac->has_robosw)
-+ if (iost & BGMAC_BCMA_IOST_ATTACHED && (bgmac->in_init || !bgmac->has_robosw))
- bgmac_idm_write(bgmac, BCMA_IOCTL,
- bgmac_idm_read(bgmac, BCMA_IOCTL) &
- ~BGMAC_BCMA_IOCTL_SW_RESET);
-@@ -1489,6 +1489,8 @@ int bgmac_enet_probe(struct bgmac *bgmac
- struct net_device *net_dev = bgmac->net_dev;
- int err;
-
-+ bgmac->in_init = true;
-+
- bgmac_chip_intrs_off(bgmac);
-
- net_dev->irq = bgmac->irq;
-@@ -1538,6 +1540,8 @@ int bgmac_enet_probe(struct bgmac *bgmac
- net_dev->hw_features = net_dev->features;
- net_dev->vlan_features = net_dev->features;
-
-+ bgmac->in_init = false;
-+
- err = register_netdev(bgmac->net_dev);
- if (err) {
- dev_err(bgmac->dev, "Cannot register net device\n");
---- a/drivers/net/ethernet/broadcom/bgmac.h
-+++ b/drivers/net/ethernet/broadcom/bgmac.h
-@@ -511,6 +511,8 @@ struct bgmac {
- int irq;
- u32 int_mask;
-
-+ bool in_init;
-+
- /* Current MAC state */
- int mac_speed;
- int mac_duplex;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
index 10b63da..b8f3dfc 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/backport-5.4.inc
@@ -205,7 +205,6 @@
file://709-v5.8-0006-net-dsa-b53-remove-redundant-premature-assignment-to.patch \
file://710-v5.16-0001-net-bgmac-improve-handling-PHY.patch \
file://710-v5.16-0002-net-bgmac-support-MDIO-described-in-DT.patch \
- file://711-v6.3-bgmac-fix-initial-chip-reset-to-support-BCM5358.patch \
file://712-v6.5-net-bgmac-postpone-turning-IRQs-off-to-avoid-SoC-han.patch \
file://716-v5.5-net-sfp-move-fwnode-parsing-into-sfp-bus-layer.patch \
file://717-v5.5-net-sfp-rework-upstream-interface.patch \
@@ -301,8 +300,6 @@
file://900-v5.9-0002-leds-Add-multicolor-ID-to-the-color-ID-list.patch \
file://900-v5.9-0003-leds-add-RGB-color-option-as-that-is-different-from-.patch \
file://999-1410-mtd-spinand-gigadevice-Support-for-modify-GD-Serial-NAND-from-v6-4-9.patch \
- file://999-1900-lib-add-Dhrystone-benchmark-test.patch \
- file://999-2210-v6.1-iio-adc-add-rtq6056-support.patch \
file://999-2310-v5.7-mtd-nand-spi-rework-detect-procedure-for-different-read-id-op.patch \
file://999-2312-mtd-spinand-macronix-Add-support-for-MX31LF1GE4BC.patch \
file://999-2313-mtd-spinand-macronix-Add-support-for-MX31UF1GE4BC.patch \
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-emmc-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-emmc-rfb.dts
index 40c41b6..9c0c072 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-emmc-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-emmc-rfb.dts
@@ -32,15 +32,22 @@
regulator-always-on;
};
- sound {
- compatible = "mediatek,mt7986-wm8960-machine";
- mediatek,platform = <&afe>;
+ sound_wm8960 {
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-gsw-spim-nand-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-gsw-spim-nand-rfb.dts
index b9faeec..af0c1c3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-gsw-spim-nand-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-gsw-spim-nand-rfb.dts
@@ -21,15 +21,22 @@
reg = <0 0x40000000 0 0x10000000>;
};
- sound {
- compatible = "mediatek,mt7986-wm8960-machine";
- mediatek,platform = <&afe>;
+ sound_wm8960 {
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-sd-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-sd-rfb.dts
index 32f9320..de4569c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-sd-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-sd-rfb.dts
@@ -14,15 +14,22 @@
reg = <0 0x40000000 0 0x10000000>;
};
- sound {
- compatible = "mediatek,mt7986-wm8960-machine";
- mediatek,platform = <&afe>;
+ sound_wm8960 {
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
reg_3p3v: regulator-3p3v {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-spim-nand-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-spim-nand-rfb.dts
index 9080933..28f576a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-spim-nand-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-spim-nand-rfb.dts
@@ -14,15 +14,22 @@
reg = <0 0x40000000 0 0x10000000>;
};
- sound {
- compatible = "mediatek,mt7986-wm8960-machine";
- mediatek,platform = <&afe>;
+ sound_wm8960 {
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-spim-nor-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-spim-nor-rfb.dts
index 85ee3b7..7bd9be8 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-spim-nor-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-2500wan-spim-nor-rfb.dts
@@ -14,15 +14,22 @@
reg = <0 0x40000000 0 0x10000000>;
};
- sound {
- compatible = "mediatek,mt7986-wm8960-machine";
- mediatek,platform = <&afe>;
+ sound_wm8960 {
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-emmc-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-emmc-rfb.dts
index 91c2234..fcde1dc 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-emmc-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-emmc-rfb.dts
@@ -33,21 +33,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-snfi-nand-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-snfi-nand-rfb.dts
index d7ec46c..e56a291 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-snfi-nand-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-snfi-nand-rfb.dts
@@ -15,21 +15,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-spim-nand-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-spim-nand-rfb.dts
index 472232d..59afe17 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-spim-nand-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-spim-nand-rfb.dts
@@ -15,21 +15,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-spim-nor-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-spim-nor-rfb.dts
index 1e125c6..bf55f74 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-spim-nor-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a-spim-nor-rfb.dts
@@ -15,21 +15,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a.dtsi
index bf62aa1..1750c0a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm/boot/dts/mt7986a.dtsi
@@ -745,7 +745,7 @@
};
afe: audio-controller@11210000 {
- compatible = "mediatek,mt79xx-audio";
+ compatible = "mediatek,mt7986-afe";
reg = <0 0x11210000 0 0x9000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&infracfg_ao CK_INFRA_AUD_BUS_CK>,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-gsw.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-gsw.dts
index 192a457..cad1f45 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-gsw.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-gsw.dts
@@ -71,21 +71,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
gsw: gsw@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-rfb.dts
index 726447f..21e54f6 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981-spim-nand-rfb.dts
@@ -71,21 +71,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981.dtsi
index 3b304d5..91415e4 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7981.dtsi
@@ -507,6 +507,8 @@
<GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>;
chip_id = <0x7981>;
memory-region = <&wmcpu_emi>;
+ nvmem-cells = <&consys_variant>;
+ nvmem-cell-names = "variant";
};
wed_pcie: wed_pcie@10003000 {
@@ -634,6 +636,10 @@
reg = <0x274 0xc>;
};
+ consys_variant: consys@284 {
+ reg = <0x284 0x4>;
+ };
+
phy_calibration: calib@8dc {
reg = <0x8dc 0x10>;
};
@@ -655,7 +661,7 @@
};
afe: audio-controller@11210000 {
- compatible = "mediatek,mt79xx-audio";
+ compatible = "mediatek,mt7981-afe", "mediatek,mt7986-afe";
reg = <0 0x11210000 0 0x9000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&infracfg_ao CK_INFRA_AUD_BUS_CK>,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-emmc-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-emmc-rfb.dts
index 40c41b6..9c0c072 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-emmc-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-emmc-rfb.dts
@@ -32,15 +32,22 @@
regulator-always-on;
};
- sound {
- compatible = "mediatek,mt7986-wm8960-machine";
- mediatek,platform = <&afe>;
+ sound_wm8960 {
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-gsw-spim-nand-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-gsw-spim-nand-rfb.dts
index b9faeec..af0c1c3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-gsw-spim-nand-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-gsw-spim-nand-rfb.dts
@@ -21,15 +21,22 @@
reg = <0 0x40000000 0 0x10000000>;
};
- sound {
- compatible = "mediatek,mt7986-wm8960-machine";
- mediatek,platform = <&afe>;
+ sound_wm8960 {
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-sd-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-sd-rfb.dts
index 32f9320..de4569c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-sd-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-sd-rfb.dts
@@ -14,15 +14,22 @@
reg = <0 0x40000000 0 0x10000000>;
};
- sound {
- compatible = "mediatek,mt7986-wm8960-machine";
- mediatek,platform = <&afe>;
+ sound_wm8960 {
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
reg_3p3v: regulator-3p3v {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nand-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nand-rfb.dts
index 9080933..28f576a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nand-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nand-rfb.dts
@@ -14,15 +14,22 @@
reg = <0 0x40000000 0 0x10000000>;
};
- sound {
- compatible = "mediatek,mt7986-wm8960-machine";
- mediatek,platform = <&afe>;
+ sound_wm8960 {
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nor-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nor-rfb.dts
index 85ee3b7..7bd9be8 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nor-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nor-rfb.dts
@@ -14,15 +14,22 @@
reg = <0 0x40000000 0 0x10000000>;
};
- sound {
- compatible = "mediatek,mt7986-wm8960-machine";
- mediatek,platform = <&afe>;
+ sound_wm8960 {
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-emmc-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-emmc-rfb.dts
index 91c2234..fcde1dc 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-emmc-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-emmc-rfb.dts
@@ -33,21 +33,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-snfi-nand-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-snfi-nand-rfb.dts
index d7ec46c..e56a291 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-snfi-nand-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-snfi-nand-rfb.dts
@@ -15,21 +15,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-spim-nand-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-spim-nand-rfb.dts
index 472232d..59afe17 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-spim-nand-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-spim-nand-rfb.dts
@@ -15,21 +15,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-spim-nor-rfb.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-spim-nor-rfb.dts
index 1e125c6..bf55f74 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-spim-nor-rfb.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-spim-nor-rfb.dts
@@ -15,21 +15,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "okay";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
index bf62aa1..1750c0a 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
@@ -745,7 +745,7 @@
};
afe: audio-controller@11210000 {
- compatible = "mediatek,mt79xx-audio";
+ compatible = "mediatek,mt7986-afe";
reg = <0 0x11210000 0 0x9000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&infracfg_ao CK_INFRA_AUD_BUS_CK>,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
index 5d9357d..51a1c81 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
@@ -436,9 +436,8 @@
phyfw: phy-firmware@f000000 {
compatible = "mediatek,2p5gphy-fw";
- reg = <0 0x0f000000 0 0x8000>,
- <0 0x0f100000 0 0x20000>,
- <0 0x0f0f0000 0 0x200>;
+ reg = <0 0x0f100000 0 0x20000>,
+ <0 0x0f0f0018 0 0x20>;
};
boottrap: boottrap@1001f6f0 {
@@ -600,7 +599,7 @@
};
afe: audio-controller@11210000 {
- compatible = "mediatek,mt79xx-audio";
+ compatible = "mediatek,mt7988-afe", "mediatek,mt7986-afe";
reg = <0 0x11210000 0 0x9000>;
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&infracfg_ao CK_INFRA_66M_AUD_SLV_BCK>,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
index 5701c3e..785bf71 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-88d-10g-spim-nand.dts
@@ -77,21 +77,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts
index 3d21585..9dcd2b7 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand-CASAN.dts
@@ -73,21 +73,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
index 32e2b15..7bd3e26 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
@@ -73,21 +73,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
index 7f7ddfd..37b7fb6 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-i2p5g-spim-nand.dts
@@ -315,6 +315,8 @@
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
reg = <15>;
+ power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
+ power-domain-names = "i2p5gbe-pd";
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "xgmii";
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
index 8176802..0aa4012 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-emmc.dts
@@ -246,6 +246,8 @@
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
reg = <15>;
+ power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
+ power-domain-names = "i2p5gbe-pd";
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "xgmii";
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
index aee27de..fea639f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sd.dts
@@ -237,6 +237,8 @@
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
reg = <15>;
+ power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
+ power-domain-names = "i2p5gbe-pd";
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "xgmii";
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sfp-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sfp-spim-nand.dts
index ed91a18..00a3179 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sfp-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-sfp-spim-nand.dts
@@ -368,6 +368,8 @@
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
reg = <15>;
+ power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
+ power-domain-names = "i2p5gbe-pd";
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "xgmii";
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
index 2df4cc2..09b1772 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-snfi-nand.dts
@@ -272,6 +272,8 @@
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
reg = <15>;
+ power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
+ power-domain-names = "i2p5gbe-pd";
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "xgmii";
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts
index 9f3bb0f..a938ea8 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand-CASAN.dts
@@ -77,21 +77,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
@@ -412,6 +425,8 @@
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
reg = <15>;
+ power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
+ power-domain-names = "i2p5gbe-pd";
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "xgmii";
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
index 1f8952d..11d872e 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nand.dts
@@ -77,21 +77,34 @@
};
sound_wm8960 {
- compatible = "mediatek,mt79xx-wm8960-machine";
- mediatek,platform = <&afe>;
+ compatible = "mediatek,mt7986-wm8960-sound";
audio-routing = "Headphone", "HP_L",
"Headphone", "HP_R",
"LINPUT1", "AMIC",
"RINPUT1", "AMIC";
- mediatek,audio-codec = <&wm8960>;
+
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
};
sound_si3218x {
- compatible = "mediatek,mt79xx-si3218x-machine";
- mediatek,platform = <&afe>;
- mediatek,ext-codec = <&proslic_spi>;
+ compatible = "mediatek,mt7986-si3218x-sound";
status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
};
};
@@ -412,6 +425,8 @@
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
reg = <15>;
+ power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
+ power-domain-names = "i2p5gbe-pd";
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "xgmii";
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
index e8e3a69..5cb069e 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-spim-nor.dts
@@ -264,6 +264,8 @@
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
reg = <15>;
+ power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
+ power-domain-names = "i2p5gbe-pd";
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "xgmii";
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-spim-nand.dts
new file mode 100644
index 0000000..d844ddb
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-10g-wan-spim-nand.dts
@@ -0,0 +1,549 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Author: Sam.Shih <sam.shih@mediatek.com>
+ */
+
+/dts-v1/;
+#include "mt7988.dtsi"
+
+/ {
+ model = "MediaTek MT7988D DSA 10G WAN SPIM-NAND RFB";
+ compatible = "mediatek,mt7988d-dsa-10g-wan-spim-snand",
+ /* Reserve this for DVFS if creating new dts */
+ "mediatek,mt7988";
+
+ chosen {
+ bootargs = "console=ttyS0,115200n1 loglevel=8 \
+ earlycon=uart8250,mmio32,0x11000000 \
+ pci=pcie_bus_perf";
+ };
+
+ cpus {
+ /delete-node/ cpu@3;
+ };
+
+ memory {
+ reg = <0 0x40000000 0 0x10000000>;
+ };
+
+ nmbm_spim_nand {
+ compatible = "generic,nmbm";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ lower-mtd-device = <&spi_nand>;
+ forced-create;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "BL2";
+ reg = <0x00000 0x0100000>;
+ read-only;
+ };
+
+ partition@100000 {
+ label = "u-boot-env";
+ reg = <0x0100000 0x0080000>;
+ };
+
+ factory: partition@180000 {
+ label = "Factory";
+ reg = <0x180000 0x0400000>;
+ };
+
+ partition@580000 {
+ label = "FIP";
+ reg = <0x580000 0x0200000>;
+ };
+
+ partition@780000 {
+ label = "ubi";
+ reg = <0x780000 0x7080000>;
+ };
+ };
+ };
+
+ wsys_adie: wsys_adie@0 {
+ // fpga cases need to manual change adie_id / sku_type for dvt only
+ compatible = "mediatek,rebb-mt7988-adie";
+ adie_id = <7976>;
+ sku_type = <3000>;
+ };
+
+ sound_wm8960 {
+ compatible = "mediatek,mt7986-wm8960-sound";
+ audio-routing = "Headphone", "HP_L",
+ "Headphone", "HP_R",
+ "LINPUT1", "AMIC",
+ "RINPUT1", "AMIC";
+
+ status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&wm8960>;
+ };
+ };
+
+ sound_si3218x {
+ compatible = "mediatek,mt7986-si3218x-sound";
+ status = "disabled";
+
+ platform {
+ sound-dai = <&afe>;
+ };
+
+ codec {
+ sound-dai = <&proslic_spi>;
+ };
+ };
+};
+
+&fan {
+ pwms = <&pwm 0 50000 0>;
+ status = "okay";
+};
+
+&afe {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcm_pins>;
+ status = "okay";
+};
+
+&pwm {
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ status = "okay";
+
+ rt5190a_64: rt5190a@64 {
+ compatible = "richtek,rt5190a";
+ reg = <0x64>;
+ /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/
+ vin2-supply = <&rt5190_buck1>;
+ vin3-supply = <&rt5190_buck1>;
+ vin4-supply = <&rt5190_buck1>;
+
+ regulators {
+ rt5190_buck1: buck1 {
+ regulator-name = "rt5190a-buck1";
+ regulator-min-microvolt = <5090000>;
+ regulator-max-microvolt = <5090000>;
+ regulator-allowed-modes =
+ <RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+ regulator-boot-on;
+ };
+ buck2 {
+ regulator-name = "vcore";
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-boot-on;
+ };
+ buck3 {
+ regulator-name = "proc";
+ 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 =
+ <RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
+ regulator-boot-on;
+ };
+ ldo {
+ regulator-name = "rt5190a-ldo";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-boot-on;
+ };
+ };
+ };
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+ status = "okay";
+
+ wm8960: wm8960@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ };
+};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_flash_pins>;
+ status = "okay";
+
+ spi_nand: spi_nand@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-nand";
+ spi-cal-enable;
+ spi-cal-mode = "read-data";
+ spi-cal-datalen = <7>;
+ spi-cal-data = /bits/ 8 <0x53 0x50 0x49 0x4E 0x41 0x4E 0x44>;
+ spi-cal-addrlen = <5>;
+ spi-cal-addr = /bits/ 32 <0x0 0x0 0x0 0x0 0x0>;
+ reg = <0>;
+ spi-max-frequency = <52000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ };
+};
+
+&spi1 {
+ pinctrl-names = "default";
+ /* pin shared with snfi */
+ pinctrl-0 = <&spic_pins>;
+ status = "disabled";
+
+ 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 54 0>;
+ ig,enable-spi = <1>; /* 1: Enable, 0: Disable */
+ };
+};
+
+&pcie0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_pins>;
+ status = "okay";
+};
+
+&pcie1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_pins>;
+ status = "disabled";
+};
+
+&pcie2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2_pins>;
+ status = "disabled";
+};
+
+&pcie3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3_pins>;
+ status = "okay";
+};
+
+&pio {
+ mdio0_pins: mdio0-pins {
+ mux {
+ function = "mdio";
+ groups = "mdc_mdio0";
+ };
+
+ conf {
+ groups = "mdc_mdio0";
+ drive-strength = <MTK_DRIVE_10mA>;
+ };
+ };
+
+ gbe0_led0_pins: gbe0-pins {
+ mux {
+ function = "led";
+ groups = "gbe0_led0";
+ };
+ };
+
+ gbe1_led0_pins: gbe1-pins {
+ mux {
+ function = "led";
+ groups = "gbe1_led0";
+ };
+ };
+
+ gbe2_led0_pins: gbe2-pins {
+ mux {
+ function = "led";
+ groups = "gbe2_led0";
+ };
+ };
+
+ gbe3_led0_pins: gbe3-pins {
+ mux {
+ function = "led";
+ groups = "gbe3_led0";
+ };
+ };
+
+ i2p5gbe_led0_pins: 2p5gbe-pins {
+ mux {
+ function = "led";
+ groups = "2p5gbe_led0";
+ };
+ };
+
+ i2c0_pins: i2c0-pins-g0 {
+ mux {
+ function = "i2c";
+ groups = "i2c0_1";
+ };
+ };
+
+ pcie0_pins: pcie0-pins {
+ mux {
+ function = "pcie";
+ groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
+ "pcie_wake_n0_0";
+ };
+ };
+
+ pcie1_pins: pcie1-pins {
+ mux {
+ function = "pcie";
+ groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
+ "pcie_wake_n1_0";
+ };
+ };
+
+ pcie2_pins: pcie2-pins {
+ mux {
+ function = "pcie";
+ groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
+ "pcie_wake_n2_0";
+ };
+ };
+
+ pcie3_pins: pcie3-pins {
+ mux {
+ function = "pcie";
+ groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
+ "pcie_wake_n3_0";
+ };
+ };
+
+ spi0_flash_pins: spi0-pins {
+ mux {
+ function = "spi";
+ groups = "spi0", "spi0_wp_hold";
+ };
+ };
+
+ spic_pins: spi1-pins {
+ mux {
+ function = "spi";
+ groups = "spi1";
+ };
+ };
+
+ i2c1_pins: i2c1-pins {
+ mux {
+ function = "i2c";
+ groups = "i2c1_0";
+ };
+ };
+
+ i2s_pins: i2s-pins {
+ mux {
+ function = "audio";
+ groups = "i2s";
+ };
+ };
+
+ pcm_pins: pcm-pins {
+ mux {
+ function = "audio";
+ groups = "pcm";
+ };
+ };
+};
+
+&watchdog {
+ status = "disabled";
+};
+
+ð {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mdio0_pins>;
+ status = "okay";
+
+ gmac0: mac@0 {
+ compatible = "mediatek,eth-mac";
+ reg = <0>;
+ mac-type = "xgdm";
+ phy-mode = "10gbase-kr";
+
+ fixed-link {
+ speed = <10000>;
+ full-duplex;
+ pause;
+ };
+ };
+
+ gmac1: mac@1 {
+ compatible = "mediatek,eth-mac";
+ reg = <1>;
+ mac-type = "xgdm";
+ phy-mode = "xgmii";
+ phy-handle = <&phy0>;
+ };
+
+ gmac2: mac@2 {
+ compatible = "mediatek,eth-mac";
+ reg = <2>;
+ mac-type = "xgdm";
+ phy-mode = "usxgmii";
+ phy-handle = <&phy1>;
+ };
+
+ mdio: mdio-bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clock-frequency = <10500000>;
+
+ phy0: ethernet-phy@0 {
+ pinctrl-names = "i2p5gbe-led";
+ pinctrl-0 = <&i2p5gbe_led0_pins>;
+ reg = <15>;
+ compatible = "ethernet-phy-ieee802.3-c45";
+ phy-mode = "xgmii";
+ };
+
+ phy1: ethernet-phy@8 {
+ reg = <8>;
+ compatible = "ethernet-phy-ieee802.3-c45";
+ reset-gpios = <&pio 3 1>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
+ mdi-reversal = /bits/ 16 <1>;
+ };
+
+ switch@0 {
+ compatible = "mediatek,mt7988";
+ reg = <31>;
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ label = "lan0";
+ phy-mode = "gmii";
+ phy-handle = <&sphy0>;
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "lan1";
+ phy-mode = "gmii";
+ phy-handle = <&sphy1>;
+ };
+
+ port@2 {
+ reg = <2>;
+ label = "lan2";
+ phy-mode = "gmii";
+ phy-handle = <&sphy2>;
+ };
+
+ port@3 {
+ reg = <3>;
+ label = "lan3";
+ phy-mode = "gmii";
+ phy-handle = <&sphy3>;
+ };
+
+ port@6 {
+ reg = <6>;
+ label = "cpu";
+ ethernet = <&gmac0>;
+ phy-mode = "10gbase-kr";
+
+ fixed-link {
+ speed = <10000>;
+ full-duplex;
+ pause;
+ };
+ };
+ };
+
+ mdio {
+ compatible = "mediatek,dsa-slave-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sphy0: switch_phy0@0 {
+ compatible = "ethernet-phy-id03a2.9481";
+ reg = <0>;
+ pinctrl-names = "gbe-led";
+ pinctrl-0 = <&gbe0_led0_pins>;
+ nvmem-cells = <&phy_calibration_p0>;
+ nvmem-cell-names = "phy-cal-data";
+ };
+
+ sphy1: switch_phy1@1 {
+ compatible = "ethernet-phy-id03a2.9481";
+ reg = <1>;
+ pinctrl-names = "gbe-led";
+ pinctrl-0 = <&gbe1_led0_pins>;
+ nvmem-cells = <&phy_calibration_p1>;
+ nvmem-cell-names = "phy-cal-data";
+ };
+
+ sphy2: switch_phy2@2 {
+ compatible = "ethernet-phy-id03a2.9481";
+ reg = <2>;
+ pinctrl-names = "gbe-led";
+ pinctrl-0 = <&gbe2_led0_pins>;
+ nvmem-cells = <&phy_calibration_p2>;
+ nvmem-cell-names = "phy-cal-data";
+ };
+
+ sphy3: switch_phy3@3 {
+ compatible = "ethernet-phy-id03a2.9481";
+ reg = <3>;
+ pinctrl-names = "gbe-led";
+ pinctrl-0 = <&gbe3_led0_pins>;
+ nvmem-cells = <&phy_calibration_p3>;
+ nvmem-cell-names = "phy-cal-data";
+ };
+ };
+ };
+ };
+};
+
+&hnat {
+ mtketh-wan = "eth2";
+ mtketh-lan = "lan";
+ mtketh-lan2 = "eth1";
+ mtketh-max-gmac = <3>;
+ status = "okay";
+};
+
+&slot0 {
+ mt7996@0,0 {
+ reg = <0x0000 0 0 0 0>;
+ device_type = "pci";
+ mediatek,mtd-eeprom = <&factory 0x0>;
+ };
+};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts
index f3af5da..0e5064b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-dsa-e2p5g-spim-nand.dts
@@ -342,6 +342,8 @@
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
reg = <15>;
+ power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
+ power-domain-names = "i2p5gbe-pd";
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "xgmii";
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts
index df35a38..9308de6 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-sfp-spim-nand.dts
@@ -357,6 +357,8 @@
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
reg = <15>;
+ power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
+ power-domain-names = "i2p5gbe-pd";
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "xgmii";
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
index 8b9fe35..e939bff 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988d-gsw-10g-spim-nand.dts
@@ -388,6 +388,8 @@
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
reg = <15>;
+ power-domains = <&topmisc MT7988_POWER_DOMAIN_ETH2P5>;
+ power-domain-names = "i2p5gbe-pd";
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "xgmii";
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 6cf9fc5..010c992 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -444,7 +444,7 @@
/* Force Port1 XGMAC Link Up */
val = mtk_r32(eth, MTK_XGMAC_STS(MTK_GMAC1_ID));
- mtk_w32(eth, val | MTK_XGMAC_FORCE_LINK(MTK_GMAC1_ID),
+ mtk_w32(eth, val | MTK_XGMAC_FORCE_MODE(MTK_GMAC1_ID),
MTK_XGMAC_STS(MTK_GMAC1_ID));
/* Adjust GSW bridge IPG to 11*/
@@ -573,6 +573,28 @@
return NULL;
}
+static int mtk_mac_prepare(struct phylink_config *config, unsigned int mode,
+ phy_interface_t iface)
+{
+ struct mtk_mac *mac = container_of(config, struct mtk_mac,
+ phylink_config);
+ u32 val;
+
+ if (mac->type == MTK_XGDM_TYPE && mac->id != MTK_GMAC1_ID) {
+ val = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
+ val &= 0xfffffff0;
+ val |= XMAC_MCR_TRX_DISABLE;
+ mtk_w32(mac->hw, val, MTK_XMAC_MCR(mac->id));
+
+ val = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
+ val |= MTK_XGMAC_FORCE_MODE(mac->id);
+ val &= ~MTK_XGMAC_FORCE_LINK(mac->id);
+ mtk_w32(mac->hw, val, MTK_XGMAC_STS(mac->id));
+ }
+
+ return 0;
+}
+
static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
const struct phylink_link_state *state)
{
@@ -702,6 +724,9 @@
regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
spin_unlock(ð->syscfg0_lock);
+ /* Save the syscfg0 value for mac_finish */
+ mac->syscfg0 = val;
+
mac->interface = state->interface;
}
@@ -721,9 +746,6 @@
/* Decide how GMAC and SGMIISYS be mapped */
sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
0 : mac->id;
-
- /* Save the syscfg0 value for mac_finish */
- mac->syscfg0 = val;
spin_unlock(ð->syscfg0_lock);
} else if (state->interface == PHY_INTERFACE_MODE_USXGMII ||
state->interface == PHY_INTERFACE_MODE_10GKR ||
@@ -987,7 +1009,6 @@
id = mtk_mac2xgmii_id(eth, mac->id);
mpcs = ð->usxgmii->pcs[id];
- cancel_delayed_work_sync(&mpcs->link_poll);
}
}
@@ -997,7 +1018,7 @@
{
struct mtk_mac *mac = container_of(config, struct mtk_mac,
phylink_config);
- u32 mcr, mcr_cur, sts, force_link;
+ u32 mcr, mcr_cur, sts;
mac->speed = speed;
@@ -1022,7 +1043,8 @@
}
/* Configure duplex */
- if (duplex == DUPLEX_FULL)
+ if (duplex == DUPLEX_FULL ||
+ interface == PHY_INTERFACE_MODE_SGMII)
mcr |= MAC_MCR_FORCE_DPX;
/* Configure pause modes -
@@ -1042,27 +1064,17 @@
if (mode == MLO_AN_PHY && phy)
mtk_setup_eee(mac, phy_init_eee(phy, false) >= 0);
} else if (mac->type == MTK_XGDM_TYPE && mac->id != MTK_GMAC1_ID) {
+ if (mode == MLO_AN_INBAND)
+ mdelay(1000);
+
/* Eliminate the interference(before link-up) caused by PHY noise */
mtk_m32(mac->hw, XMAC_LOGIC_RST, 0x0, MTK_XMAC_LOGIC_RST(mac->id));
mdelay(20);
mtk_m32(mac->hw, XMAC_GLB_CNTCLR, 0x1, MTK_XMAC_CNT_CTRL(mac->id));
- switch (mac->id) {
- case MTK_GMAC2_ID:
- force_link = (mac->interface ==
- PHY_INTERFACE_MODE_XGMII) ?
- MTK_XGMAC_FORCE_LINK(mac->id) : 0;
- sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
- mtk_w32(mac->hw, sts | force_link,
- MTK_XGMAC_STS(mac->id));
- break;
- case MTK_GMAC3_ID:
- sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
- mtk_w32(mac->hw,
- sts | MTK_XGMAC_FORCE_LINK(mac->id),
- MTK_XGMAC_STS(mac->id));
- break;
- }
+ sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
+ sts |= MTK_XGMAC_FORCE_LINK(mac->id);
+ mtk_w32(mac->hw, sts, MTK_XGMAC_STS(mac->id));
mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id));
@@ -1220,6 +1232,7 @@
.validate = mtk_validate,
.mac_select_pcs = mtk_mac_select_pcs,
.mac_link_state = mtk_mac_pcs_get_state,
+ .mac_prepare = mtk_mac_prepare,
.mac_config = mtk_mac_config,
.mac_finish = mtk_mac_finish,
.mac_link_down = mtk_mac_link_down,
@@ -2966,6 +2979,68 @@
return cnt;
}
+static int mtk_hwlro_add_ipaddr_idx(struct net_device *dev, u32 ip4dst)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ u32 reg_val;
+ int i;
+
+ /* check for duplicate IP address in the current DIP list */
+ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++) {
+ reg_val = mtk_r32(eth, MTK_LRO_DIP_DW0_CFG(i));
+ if (reg_val == ip4dst)
+ break;
+ }
+
+ if (i <= MTK_HW_LRO_RING_NUM) {
+ netdev_warn(dev, "Duplicate IP address at DIP(%d)!\n", i);
+ return -EEXIST;
+ }
+
+ /* find out available DIP index */
+ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++) {
+ reg_val = mtk_r32(eth, MTK_LRO_DIP_DW0_CFG(i));
+ if (reg_val == 0UL)
+ break;
+ }
+
+ if (i > MTK_HW_LRO_RING_NUM) {
+ netdev_warn(dev, "DIP index is currently out of resource!\n");
+ return -EBUSY;
+ }
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2))
+ i -= 1;
+
+ return i;
+}
+
+static int mtk_hwlro_get_ipaddr_idx(struct net_device *dev, u32 ip4dst)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ u32 reg_val;
+ int i;
+
+ /* find out DIP index that matches the given IP address */
+ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++) {
+ reg_val = mtk_r32(eth, MTK_LRO_DIP_DW0_CFG(i));
+ if (reg_val == ip4dst)
+ break;
+ }
+
+ if (i > MTK_HW_LRO_RING_NUM) {
+ netdev_warn(dev, "DIP address is not exist!\n");
+ return -ENOENT;
+ }
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_RX_V2))
+ i -= 1;
+
+ return i;
+}
+
static int mtk_hwlro_add_ipaddr(struct net_device *dev,
struct ethtool_rxnfc *cmd)
{
@@ -2974,15 +3049,19 @@
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
int hwlro_idx;
+ u32 ip4dst;
if ((fsp->flow_type != TCP_V4_FLOW) ||
(!fsp->h_u.tcp_ip4_spec.ip4dst) ||
(fsp->location > 1))
return -EINVAL;
- mac->hwlro_ip[fsp->location] = htonl(fsp->h_u.tcp_ip4_spec.ip4dst);
- hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + fsp->location;
+ ip4dst = htonl(fsp->h_u.tcp_ip4_spec.ip4dst);
+ hwlro_idx = mtk_hwlro_add_ipaddr_idx(dev, ip4dst);
+ if (hwlro_idx < 0)
+ return hwlro_idx;
+ mac->hwlro_ip[fsp->location] = ip4dst;
mac->hwlro_ip_cnt = mtk_hwlro_get_ip_cnt(mac);
mtk_hwlro_val_ipaddr(eth, hwlro_idx, mac->hwlro_ip[fsp->location]);
@@ -2998,13 +3077,17 @@
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
int hwlro_idx;
+ u32 ip4dst;
if (fsp->location > 1)
return -EINVAL;
- mac->hwlro_ip[fsp->location] = 0;
- hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + fsp->location;
+ ip4dst = mac->hwlro_ip[fsp->location];
+ hwlro_idx = mtk_hwlro_get_ipaddr_idx(dev, ip4dst);
+ if (hwlro_idx < 0)
+ return hwlro_idx;
+ mac->hwlro_ip[fsp->location] = 0;
mac->hwlro_ip_cnt = mtk_hwlro_get_ip_cnt(mac);
mtk_hwlro_inval_ipaddr(eth, hwlro_idx);
@@ -3012,6 +3095,24 @@
return 0;
}
+static void mtk_hwlro_netdev_enable(struct net_device *dev)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ int i, hwlro_idx;
+
+ for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) {
+ if (mac->hwlro_ip[i] == 0)
+ continue;
+
+ hwlro_idx = mtk_hwlro_get_ipaddr_idx(dev, mac->hwlro_ip[i]);
+ if (hwlro_idx < 0)
+ continue;
+
+ mtk_hwlro_val_ipaddr(eth, hwlro_idx, mac->hwlro_ip[i]);
+ }
+}
+
static void mtk_hwlro_netdev_disable(struct net_device *dev)
{
struct mtk_mac *mac = netdev_priv(dev);
@@ -3019,8 +3120,14 @@
int i, hwlro_idx;
for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) {
+ if (mac->hwlro_ip[i] == 0)
+ continue;
+
+ hwlro_idx = mtk_hwlro_get_ipaddr_idx(dev, mac->hwlro_ip[i]);
+ if (hwlro_idx < 0)
+ continue;
+
mac->hwlro_ip[i] = 0;
- hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + i;
mtk_hwlro_inval_ipaddr(eth, hwlro_idx);
}
@@ -3210,13 +3317,17 @@
{
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
+ netdev_features_t lro;
int err = 0;
if (!((dev->features ^ features) & MTK_SET_FEATURES))
return 0;
- if (!(features & NETIF_F_LRO))
+ lro = dev->features & NETIF_F_LRO;
+ if (!(features & NETIF_F_LRO) && lro)
mtk_hwlro_netdev_disable(dev);
+ else if ((features & NETIF_F_LRO) && !lro)
+ mtk_hwlro_netdev_enable(dev);
if (!(features & NETIF_F_HW_VLAN_CTAG_RX))
mtk_w32(eth, 0, MTK_CDMP_EG_CTRL);
@@ -4150,7 +4261,7 @@
pr_info("[%s] mtk_stop starts !\n", __func__);
/* 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);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 7811de7..913302e 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -676,7 +676,8 @@
/* 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_XGMAC_FORCE_MODE(x) ((x == MTK_GMAC2_ID) ? BIT(31) : BIT(15))
+#define MTK_XGMAC_FORCE_LINK(x) ((x == MTK_GMAC2_ID) ? BIT(27) : BIT(11))
#define MTK_USXGMII_PCS_LINK BIT(8)
#define MTK_XGMAC_RX_FC BIT(5)
#define MTK_XGMAC_TX_FC BIT(4)
@@ -1732,7 +1733,7 @@
struct mtk_eth *eth;
struct regmap *regmap;
struct regmap *regmap_pextp;
- struct delayed_work link_poll;
+ spinlock_t regmap_lock;
phy_interface_t interface;
unsigned int mode;
u8 id;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
index 8f11a83..6d86f25 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
@@ -867,6 +867,11 @@
#endif
#define CFG_PPE_NUM (hnat_priv->ppe_num)
+/* If the user wants to set skb->mark to prevent hardware acceleration
+ * for the packet flow.
+ */
+#define HNAT_EXCEPTION_TAG 0x99
+
struct mib_entry {
u32 byt_cnt_l;
u16 byt_cnt_h;
@@ -1218,13 +1223,11 @@
#define UDF_PINGPONG_IFIDX GENMASK(3, 0)
#define UDF_HNAT_PRE_FILLED BIT(4)
-#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-#define TPORT_FLAG(dev, skb, qid) \
+#define HQOS_FLAG(dev, skb, qid) \
((IS_HQOS_UL_MODE && IS_WAN(dev)) || \
(IS_HQOS_DL_MODE && IS_LAN_GRP(dev)) || \
(IS_PPPQ_MODE && (IS_PPPQ_PATH(dev, skb) || \
qid >= MAX_PPPQ_PORT_NUM)))
-#endif
extern const struct of_device_id of_hnat_match[];
extern struct mtk_hnat *hnat_priv;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
index f6c6499..7efe182 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
@@ -2069,11 +2069,9 @@
return -EFAULT;
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
- if (rate > 100000000 || rate < 0 ||
- rate > 100000000 || rate < 0)
+ if (rate > 10000000 || rate < 0)
#else
- if (rate > 10000000 || rate < 0 ||
- rate > 10000000 || rate < 0)
+ if (rate > 1000000 || rate < 0)
#endif
return -EINVAL;
@@ -2228,11 +2226,11 @@
line[length] = '\0';
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
- if (max_rate > 100000000 || max_rate < 0 ||
- min_rate > 100000000 || min_rate < 0)
-#else
if (max_rate > 10000000 || max_rate < 0 ||
min_rate > 10000000 || min_rate < 0)
+#else
+ if (max_rate > 1000000 || max_rate < 0 ||
+ min_rate > 1000000 || min_rate < 0)
#endif
return -EINVAL;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
index 7af79ee..75ae019 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
@@ -1747,7 +1747,7 @@
return 0;
}
- if (IS_HQOS_MODE || skb->mark >= MAX_PPPQ_PORT_NUM)
+ if (IS_HQOS_MODE || (skb->mark & MTK_QDMA_TX_MASK) >= MAX_PPPQ_PORT_NUM)
qid = skb->mark & (MTK_QDMA_TX_MASK);
else if (IS_PPPQ_MODE && IS_PPPQ_PATH(dev, skb))
qid = port_id & MTK_QDMA_TX_MASK;
@@ -1780,18 +1780,13 @@
}
}
- if (FROM_EXT(skb) || skb_hnat_sport(skb) == NR_QDMA_PORT ||
- (IS_PPPQ_MODE && (qid < MAX_PPPQ_PORT_NUM) &&
- !IS_DSA_LAN(dev) && !IS_DSA_WAN(dev)))
+ if (FROM_EXT(skb) || skb_hnat_sport(skb) == NR_QDMA_PORT)
entry.ipv4_hnapt.iblk2.fqos = 0;
else
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
- entry.ipv4_hnapt.tport_id = TPORT_FLAG(dev, skb, qid) ? 1 : 0;
+ entry.ipv4_hnapt.tport_id = HQOS_FLAG(dev, skb, qid) ? 1 : 0;
#else
- entry.ipv4_hnapt.iblk2.fqos =
- (!IS_PPPQ_MODE ||
- (IS_PPPQ_MODE &&
- IS_PPPQ_PATH(dev, skb)));
+ entry.ipv4_hnapt.iblk2.fqos = HQOS_FLAG(dev, skb, qid) ? 1 : 0;
#endif
} else {
entry.ipv4_hnapt.iblk2.fqos = 0;
@@ -1821,9 +1816,7 @@
}
}
- if (FROM_EXT(skb) ||
- (IS_PPPQ_MODE && (qid < MAX_PPPQ_PORT_NUM) &&
- !IS_DSA_LAN(dev) && !IS_DSA_WAN(dev)))
+ if (FROM_EXT(skb) || skb_hnat_sport(skb) == NR_QDMA_PORT)
entry.ipv6_5t_route.iblk2.fqos = 0;
else
#if defined(CONFIG_MEDIATEK_NETSYS_V3)
@@ -1831,23 +1824,20 @@
case IPV4_MAP_E:
case IPV4_MAP_T:
entry.ipv4_mape.tport_id =
- TPORT_FLAG(dev, skb, qid) ? 1 : 0;
+ HQOS_FLAG(dev, skb, qid) ? 1 : 0;
break;
case IPV6_HNAPT:
case IPV6_HNAT:
entry.ipv6_hnapt.tport_id =
- TPORT_FLAG(dev, skb, qid) ? 1 : 0;
+ HQOS_FLAG(dev, skb, qid) ? 1 : 0;
break;
default:
entry.ipv6_5t_route.tport_id =
- TPORT_FLAG(dev, skb, qid) ? 1 : 0;
+ HQOS_FLAG(dev, skb, qid) ? 1 : 0;
break;
}
#else
- entry.ipv6_5t_route.iblk2.fqos =
- (!IS_PPPQ_MODE ||
- (IS_PPPQ_MODE &&
- IS_PPPQ_PATH(dev, skb)));
+ entry.ipv6_5t_route.iblk2.fqos = HQOS_FLAG(dev, skb, qid) ? 1 : 0;
#endif
} else {
entry.ipv6_5t_route.iblk2.fqos = 0;
@@ -2673,6 +2663,9 @@
if (unlikely(!skb_hnat_is_hashed(skb)))
return 0;
+ if (unlikely(skb->mark == HNAT_EXCEPTION_TAG))
+ return 0;
+
if (out->netdev_ops->ndo_flow_offload_check) {
out->netdev_ops->ndo_flow_offload_check(&hw_path);
out = (IS_GMAC1_MODE) ? hw_path.virt_dev : hw_path.dev;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
index 3c16948..d297994 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
@@ -112,9 +112,9 @@
#define skb_hnat_hf(skb) (((struct hnat_desc *)((skb)->head))->hf)
#define skb_hnat_amsdu(skb) (((struct hnat_desc *)((skb)->head))->amsdu)
#define skb_hnat_ppe2(skb) \
- ((skb_hnat_iface(skb) == FOE_MAGIC_GE_LAN2) && (CFG_PPE_NUM == 3))
+ ((skb_hnat_sport(skb) == NR_GMAC3_PORT) && (CFG_PPE_NUM == 3))
#define skb_hnat_ppe1(skb) \
- ((skb_hnat_iface(skb) == FOE_MAGIC_GE_WAN) && (CFG_PPE_NUM == 3))
+ ((skb_hnat_sport(skb) == NR_GMAC2_PORT) && (CFG_PPE_NUM >= 2))
#define skb_hnat_ppe(skb) \
(skb_hnat_ppe2(skb) ? 2 : (skb_hnat_ppe1(skb) ? 1 : 0))
#define headroom_iface(h) (h.iface)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
index 3cc8f90..bdb6662 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -144,7 +144,7 @@
mdelay(1);
}
-int mtk_sgmii_need_powerdown(struct mtk_sgmii_pcs *mpcs)
+int mtk_sgmii_need_powerdown(struct mtk_sgmii_pcs *mpcs, unsigned int bmcr)
{
u32 val;
@@ -153,6 +153,10 @@
if (!(val & SGMII_LINK_STATYS))
return true;
+ /* need to power down sgmii if autoneg change */
+ if ((val & SGMII_AN_ENABLE) != bmcr)
+ return true;
+
return false;
}
@@ -455,7 +459,7 @@
}
if (mpcs->interface != interface ||
- mtk_sgmii_need_powerdown(mpcs)) {
+ mtk_sgmii_need_powerdown(mpcs, bmcr)) {
link_timer = phylink_get_link_timer_ns(interface);
if (link_timer < 0)
return link_timer;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
index 0cadc85..cdb2a55 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_usxgmii.c
@@ -568,6 +568,8 @@
unsigned int an_ctrl = 0, link_timer = 0, xfi_mode = 0, adapt_mode = 0;
bool mode_changed = false;
+ spin_lock(&mpcs->regmap_lock);
+
if (interface == PHY_INTERFACE_MODE_USXGMII) {
an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF) |
USXGMII_AN_ENABLE;
@@ -656,6 +658,8 @@
else if (interface == PHY_INTERFACE_MODE_5GBASER)
mtk_usxgmii_setup_phya_5gbaser(mpcs);
+ spin_unlock(&mpcs->regmap_lock);
+
return mode_changed;
}
@@ -665,6 +669,7 @@
struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
struct mtk_eth *eth = mpcs->eth;
struct mtk_mac *mac = eth->mac[mtk_xgmii2mac_id(eth, mpcs->id)];
+ static unsigned long t_start;
u32 val = 0;
regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
@@ -727,9 +732,14 @@
state->duplex = DUPLEX_FULL;
}
- if (state->link == 0)
+ /* Reconfiguring USXGMII every second to ensure that PCS can
+ * link up with the Link Partner when a module is inserted.
+ */
+ if (state->link == 0 && time_after(jiffies, t_start + HZ)) {
+ t_start = jiffies;
mtk_usxgmii_pcs_config(pcs, MLO_AN_INBAND,
state->interface, NULL, false);
+ }
}
void mtk_usxgmii_pcs_restart_an(struct phylink_pcs *pcs)
@@ -745,25 +755,12 @@
regmap_write(mpcs->regmap, RG_PCS_AN_CTRL0, val);
}
-void mtk_usxgmii_link_poll(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct mtk_usxgmii_pcs *mpcs = container_of(dwork, struct mtk_usxgmii_pcs, link_poll);
-
- if (!mtk_usxgmii_link_status(mpcs)) {
- mtk_usxgmii_pcs_config(&mpcs->pcs, mpcs->mode,
- mpcs->interface, NULL, false);
-
- queue_delayed_work(system_power_efficient_wq, &mpcs->link_poll,
- msecs_to_jiffies(1000));
- }
-}
-
static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
phy_interface_t interface,
int speed, int duplex)
{
struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
+ unsigned long t_start = jiffies;
/* Reconfiguring USXGMII to ensure the quality of the RX signal
* after the line side link up.
@@ -771,8 +768,18 @@
mtk_usxgmii_pcs_config(pcs, mode,
interface, NULL, false);
- queue_delayed_work(system_power_efficient_wq, &mpcs->link_poll,
- msecs_to_jiffies(1000));
+ do {
+ msleep(1000);
+
+ if (mtk_usxgmii_link_status(mpcs))
+ return;
+
+ if (mpcs->mode == MLO_AN_PHY)
+ mtk_usxgmii_pcs_config(&mpcs->pcs, mode,
+ interface, NULL, false);
+ } while (time_before(jiffies, t_start + msecs_to_jiffies(3000)));
+
+ pr_warn("%s wait link up timeout!\n", __func__);
}
static const struct phylink_pcs_ops mtk_usxgmii_pcs_ops = {
@@ -804,7 +811,7 @@
ss->pcs[i].pcs.poll = true;
ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
- INIT_DELAYED_WORK(&ss->pcs[i].link_poll, mtk_usxgmii_link_poll);
+ spin_lock_init(&ss->pcs[i].regmap_lock);
of_node_put(np);
}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
index 6a1c9e0..ab87e93 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/net/phy/mediatek-2p5ge.c
@@ -7,12 +7,14 @@
#include <linux/of_platform.h>
#include <linux/pinctrl/consumer.h>
#include <linux/phy.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
-#define MEDAITEK_2P5GE_PHY_DMB_FW "mediatek-2p5ge-phy-dmb.bin"
-#define MEDIATEK_2P5GE_PHY_PMB_FW "mediatek-2p5ge-phy-pmb.bin"
+#define MT7988_2P5GE_PMB "mediatek/mt7988/i2p5ge-phy-pmb.bin"
-#define MD32_EN_CFG 0x18
-#define MD32_EN BIT(0)
+#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)
@@ -42,6 +44,14 @@
#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,
@@ -49,60 +59,100 @@
PHY_AUX_SPD_2500,
};
-static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev)
+static int mtk_2p5ge_phy_read_page(struct phy_device *phydev)
{
- int ret;
- int i;
+ 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 *pm_dev;
struct device_node *np;
- void __iomem *dmb_addr;
void __iomem *pmb_addr;
- void __iomem *mcucsr_base;
+ 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) {
+ pm_dev = dev_pm_domain_attach_by_name(dev, "i2p5gbe-pd");
+ if (IS_ERR(pm_dev)) {
+ ret = PTR_ERR(pm_dev);
+ dev_err(dev, "failed to get i2p5g pm-domain: %d\n", ret);
+ return ret;
+ }
+ if (!pm_dev->pm_domain)
+ dev_info(dev, "pm_dev domain is not ready yet\n");
+
+ /* We need to add 1 to power domain counter first so that
+ * we can correctly power off internal 2.5Gphy
+ */
+ ret = pm_runtime_get_sync(pm_dev);
+ if (ret < 0) {
+ dev_err(&phydev->mdio.dev, "failed to power on!\n");
+ return ret;
+ }
+ pm_runtime_put_sync(pm_dev);
+ ret = pm_runtime_get_sync(pm_dev);
+ if (ret < 0) {
+ dev_err(&phydev->mdio.dev, "failed to power on!\n");
+ return ret;
+ }
- np = of_find_compatible_node(NULL, NULL, "mediatek,2p5gphy-fw");
- if (!np)
- return -ENOENT;
+ 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;
- dmb_addr = of_iomap(np, 0);
- if (!dmb_addr)
- return -ENOMEM;
- pmb_addr = of_iomap(np, 1);
- if (!pmb_addr)
- return -ENOMEM;
- mcucsr_base = of_iomap(np, 2);
- if (!mcucsr_base)
- return -ENOMEM;
+ ret = request_firmware(&fw, MT7988_2P5GE_PMB, dev);
+ if (ret) {
+ dev_err(dev, "failed to load firmware: %s, ret: %d\n",
+ MT7988_2P5GE_PMB, ret);
+ return ret;
+ }
- ret = request_firmware(&fw, MEDAITEK_2P5GE_PHY_DMB_FW, dev);
- if (ret) {
- dev_err(dev, "failed to load firmware: %s, ret: %d\n",
- MEDAITEK_2P5GE_PHY_DMB_FW, ret);
- return ret;
- }
- for (i = 0; i < fw->size - 1; i += 4)
- writel(*((uint32_t *)(fw->data + i)), dmb_addr + i);
- release_firmware(fw);
+ reg = readw(md32_en_cfg_base);
+ writew(reg | DMEM_PRIORITY | PMEM_PRIORITY, md32_en_cfg_base);
- ret = request_firmware(&fw, MEDIATEK_2P5GE_PHY_PMB_FW, dev);
- if (ret) {
- dev_err(dev, "failed to load firmware: %s, ret: %d\n",
- MEDIATEK_2P5GE_PHY_PMB_FW, ret);
- return ret;
- }
- for (i = 0; i < fw->size - 1; i += 4)
- writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
- release_firmware(fw);
+ for (i = 0; i < fw->size - 1; i += 4)
+ writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
+ release_firmware(fw);
- reg = readw(mcucsr_base + MD32_EN_CFG);
- writew(reg | MD32_EN, mcucsr_base + MD32_EN_CFG);
- dev_info(dev, "Firmware loading/trigger ok.\n");
+ reg = readw(md32_en_cfg_base);
+ reg &= ~(DMEM_PRIORITY | PMEM_PRIORITY | MD32_EN);
+ writew(reg, md32_en_cfg_base);
+ writew(reg | MD32_EN, md32_en_cfg_base);
+ dev_info(dev, "Firmware loading/trigger ok.\n");
- phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LPI_PCS_DSP_CTRL,
- MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK, 0);
+ phy_priv->fw_loaded = true;
+ }
/* Setup LED */
phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
@@ -118,10 +168,20 @@
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 mt798x_2p5ge_phy_config_aneg(struct phy_device *phydev)
+static int mt7988_2p5ge_phy_config_aneg(struct phy_device *phydev)
{
bool changed = false;
u32 adv;
@@ -154,7 +214,7 @@
return genphy_c45_check_and_restart_aneg(phydev, changed);
}
-static int mt798x_2p5ge_phy_get_features(struct phy_device *phydev)
+static int mt7988_2p5ge_phy_get_features(struct phy_device *phydev)
{
int ret;
@@ -162,7 +222,7 @@
if (ret)
return ret;
- /* We don't support HDX at MAC layer on mt798x.
+ /* 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,
@@ -178,7 +238,7 @@
return 0;
}
-static int mt798x_2p5ge_phy_read_status(struct phy_device *phydev)
+static int mt7988_2p5ge_phy_read_status(struct phy_device *phydev)
{
int ret;
@@ -234,7 +294,7 @@
return 0;
}
-static int mt798x_2p5ge_phy_get_rate_matching(struct phy_device *phydev,
+static int mt7988_2p5ge_phy_get_rate_matching(struct phy_device *phydev,
phy_interface_t iface)
{
if (iface == PHY_INTERFACE_MODE_XGMII)
@@ -244,17 +304,18 @@
static struct phy_driver mtk_gephy_driver[] = {
{
- PHY_ID_MATCH_EXACT(0x00339c11),
+ PHY_ID_MATCH_MODEL(0x00339c11),
.name = "MediaTek MT798x 2.5GbE PHY",
- .config_init = mt798x_2p5ge_phy_config_init,
- .config_aneg = mt798x_2p5ge_phy_config_aneg,
- .get_features = mt798x_2p5ge_phy_get_features,
- .read_status = mt798x_2p5ge_phy_read_status,
- .get_rate_matching = mt798x_2p5ge_phy_get_rate_matching,
- //.config_intr = genphy_no_config_intr,
- //.handle_interrupt = genphy_no_ack_interrupt,
+ .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,
},
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-si3218x.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt7986/mt7986-si3218x.c
similarity index 63%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-si3218x.c
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt7986/mt7986-si3218x.c
index 6a45595..b91ee07 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-si3218x.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt7986/mt7986-si3218x.c
@@ -1,17 +1,18 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * mt79xx-si3218x.c -- MT79xx WM8960 ALSA SoC machine driver
+ * mt7986-si3218x.c -- MT7986-SI3218X ALSA SoC machine driver
*
- * Copyright (c) 2021 MediaTek Inc.
- * Author: Vic Wu <vic.wu@mediatek.com>
+ * Copyright (c) 2023 MediaTek Inc.
+ * Authors: Vic Wu <vic.wu@mediatek.com>
+ * Maso Huang <maso.huang@mediatek.com>
*/
+#include <linux/bitfield.h>
#include <linux/module.h>
#include <sound/soc.h>
-#include "mt79xx-afe-clk.h"
-#include "mt79xx-afe-common.h"
-#include "mt79xx-reg.h"
+#include "mt7986-afe-common.h"
+#include "mt7986-reg.h"
#include "../common/mtk-afe-platform-driver.h"
enum {
@@ -62,23 +63,23 @@
ETDM_FS_176K = 20,
};
-struct mt79xx_si3218x_priv {
- struct device_node *platform_node;
- struct device_node *codec_node;
-};
-
-static int mt79xx_si3218x_init(struct snd_soc_pcm_runtime *rtd)
+static int mt7986_si3218x_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ struct mt7986_afe_private *afe_priv = afe->platform_priv;
+ int ret;
/* enable clk */
- mt79xx_afe_enable_clock(afe);
- 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);
+ ret = clk_bulk_prepare_enable(afe_priv->num_clks, afe_priv->clks);
+ if (ret) {
+ dev_err(afe->dev, "Failed to enable clocks\n");
+ return ret;
+ }
+
+ 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);
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);
@@ -89,15 +90,15 @@
regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_SYNC_MASK,
ETDM_SYNC);
regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_FMT_MASK,
- ETDM_FMT(PCMA));
+ FIELD_PREP(ETDM_FMT_MASK, PCMA));
regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_BIT_LEN_MASK,
- ETDM_BIT_LEN(16));
+ FIELD_PREP(ETDM_BIT_LEN_MASK, 16 - 1));
regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_WRD_LEN_MASK,
- ETDM_WRD_LEN(16));
+ FIELD_PREP(ETDM_WRD_LEN_MASK, 16 - 1));
regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_CH_NUM_MASK,
- ETDM_CH_NUM(4));
+ FIELD_PREP(ETDM_CH_NUM_MASK, 4 - 1));
regmap_update_bits(afe->regmap, ETDM_IN5_CON0, RELATCH_SRC_MASK,
- RELATCH_SRC(APLL_CLK));
+ FIELD_PREP(RELATCH_SRC_MASK, APLL_CLK));
/* set ETDM_IN5_CON2 */
regmap_update_bits(afe->regmap, ETDM_IN5_CON2, IN_CLK_SRC_MASK,
@@ -115,15 +116,15 @@
/* set ETDM_OUT5_CON0 */
regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_FMT_MASK,
- ETDM_FMT(PCMA));
+ FIELD_PREP(ETDM_FMT_MASK, PCMA));
regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_BIT_LEN_MASK,
- ETDM_BIT_LEN(16));
+ FIELD_PREP(ETDM_BIT_LEN_MASK, 16 - 1));
regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_WRD_LEN_MASK,
- ETDM_WRD_LEN(16));
+ FIELD_PREP(ETDM_WRD_LEN_MASK, 16 - 1));
regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_CH_NUM_MASK,
- ETDM_CH_NUM(4));
+ FIELD_PREP(ETDM_CH_NUM_MASK, 4 - 1));
regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, RELATCH_SRC_MASK,
- RELATCH_SRC(APLL_CLK));
+ FIELD_PREP(RELATCH_SRC_MASK, APLL_CLK));
/* set ETDM_OUT5_CON4 */
regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, OUT_SEL_FS_MASK,
@@ -167,7 +168,7 @@
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "proslic_spi-aif")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
-static struct snd_soc_dai_link mt79xx_si3218x_dai_links[] = {
+static struct snd_soc_dai_link mt7986_si3218x_dai_links[] = {
/* FE */
{
.name = "si3218x-playback",
@@ -194,34 +195,41 @@
.dai_fmt = SND_SOC_DAIFMT_DSP_A |
SND_SOC_DAIFMT_IB_NF |
SND_SOC_DAIFMT_CBS_CFS,
- .init = mt79xx_si3218x_init,
+ .init = mt7986_si3218x_init,
.dpcm_playback = 1,
.dpcm_capture = 1,
SND_SOC_DAILINK_REG(codec),
},
};
-static struct snd_soc_card mt79xx_si3218x_card = {
- .name = "mt79xx-si3218x",
+static struct snd_soc_card mt7986_si3218x_card = {
+ .name = "mt7986-si3218x",
.owner = THIS_MODULE,
- .dai_link = mt79xx_si3218x_dai_links,
- .num_links = ARRAY_SIZE(mt79xx_si3218x_dai_links),
+ .dai_link = mt7986_si3218x_dai_links,
+ .num_links = ARRAY_SIZE(mt7986_si3218x_dai_links),
};
-static int mt79xx_si3218x_machine_probe(struct platform_device *pdev)
+static int mt7986_si3218x_machine_probe(struct platform_device *pdev)
{
- struct snd_soc_card *card = &mt79xx_si3218x_card;
+ struct snd_soc_card *card = &mt7986_si3218x_card;
struct snd_soc_dai_link *dai_link;
- struct mt79xx_si3218x_priv *priv;
+ struct device_node *platform, *codec;
+ struct device_node *platform_dai_node, *codec_dai_node;
int ret, i;
+ card->dev = &pdev->dev;
+
+ platform = of_get_child_by_name(pdev->dev.of_node, "platform");
+
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ if (platform) {
+ platform_dai_node = of_parse_phandle(platform, "sound-dai", 0);
+ of_node_put(platform);
- priv->platform_node = of_parse_phandle(pdev->dev.of_node,
- "mediatek,platform", 0);
- if (!priv->platform_node) {
+ if (!platform_dai_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;
}
@@ -229,70 +237,61 @@
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) {
+ codec_dai_node = of_parse_phandle(codec, "sound-dai", 0);
+ of_node_put(codec);
- priv->codec_node = of_parse_phandle(pdev->dev.of_node,
- "mediatek,ext-codec", 0);
- if (!priv->codec_node) {
- dev_err(&pdev->dev,
- "Property 'audio-codec' missing or invalid\n");
- 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(platform_dai_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;
+ dai_link->codecs->of_node = codec_dai_node;
}
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);
- of_node_put(priv->codec_node);
- of_node_put(priv->platform_node);
+ 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(platform_dai_node);
+ of_node_put(codec_dai_node);
return ret;
}
-static int mt79xx_si3218x_machine_remove(struct platform_device *pdev)
-{
- struct snd_soc_card *card = platform_get_drvdata(pdev);
- struct mt79xx_si3218x_priv *priv = snd_soc_card_get_drvdata(card);
-
- of_node_put(priv->codec_node);
- of_node_put(priv->platform_node);
-
- return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id mt79xx_si3218x_machine_dt_match[] = {
- {.compatible = "mediatek,mt79xx-si3218x-machine",},
- {}
+static const struct of_device_id mt7986_si3218x_machine_dt_match[] = {
+ {.compatible = "mediatek,mt7986-si3218x-sound"},
+ { /* sentinel */ }
};
-#endif
-static struct platform_driver mt79xx_si3218x_machine = {
+static struct platform_driver mt7986_si3218x_machine = {
.driver = {
- .name = "mt79xx-si3218x",
-#ifdef CONFIG_OF
- .of_match_table = mt79xx_si3218x_machine_dt_match,
-#endif
+ .name = "mt7986-si3218x",
+ .of_match_table = mt7986_si3218x_machine_dt_match,
},
- .probe = mt79xx_si3218x_machine_probe,
- .remove = mt79xx_si3218x_machine_remove,
+ .probe = mt7986_si3218x_machine_probe,
};
-module_platform_driver(mt79xx_si3218x_machine);
+module_platform_driver(mt7986_si3218x_machine);
/* Module information */
-MODULE_DESCRIPTION("MT79xx SI3218x ALSA SoC machine driver");
+MODULE_DESCRIPTION("MT7986 SI3218X ALSA SoC machine driver");
MODULE_AUTHOR("Vic Wu <vic.wu@mediatek.com>");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("mt79xx si3218x soc card");
+MODULE_ALIAS("mt7986 si3218x soc card");
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/Makefile b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/Makefile
deleted file mode 100644
index 958ad63..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-# platform driver
-snd-soc-mt79xx-afe-objs := \
- mt79xx-afe-pcm.o \
- mt79xx-afe-clk.o \
- mt79xx-dai-etdm.o
-
-obj-$(CONFIG_SND_SOC_MT79XX) += snd-soc-mt79xx-afe.o
-obj-$(CONFIG_SND_SOC_MT79XX_WM8960) += mt79xx-wm8960.o
-obj-$(CONFIG_SND_SOC_MT79XX_SI3218X) += mt79xx-si3218x.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-afe-clk.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-afe-clk.c
deleted file mode 100644
index 6f13c42..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-afe-clk.c
+++ /dev/null
@@ -1,121 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// mt79xx-afe-clk.c -- Mediatek 79xx afe clock ctrl
-//
-// Copyright (c) 2021 MediaTek Inc.
-// Author: Vic Wu <vic.wu@mediatek.com>
-
-#include <linux/clk.h>
-
-#include "mt79xx-afe-common.h"
-#include "mt79xx-afe-clk.h"
-#include "mt79xx-reg.h"
-
-enum {
- CK_INFRA_AUD_BUS_CK = 0,
- CK_INFRA_AUD_26M_CK,
- CK_INFRA_AUD_L_CK,
- CK_INFRA_AUD_AUD_CK,
- CK_INFRA_AUD_EG2_CK,
- CLK_NUM
-};
-
-static const char *aud_clks[CLK_NUM] = {
- [CK_INFRA_AUD_BUS_CK] = "aud_bus_ck",
- [CK_INFRA_AUD_26M_CK] = "aud_26m_ck",
- [CK_INFRA_AUD_L_CK] = "aud_l_ck",
- [CK_INFRA_AUD_AUD_CK] = "aud_aud_ck",
- [CK_INFRA_AUD_EG2_CK] = "aud_eg2_ck",
-};
-
-int mt79xx_init_clock(struct mtk_base_afe *afe)
-{
- struct mt79xx_afe_private *afe_priv = afe->platform_priv;
- int i;
-
- afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM, sizeof(*afe_priv->clk),
- GFP_KERNEL);
- if (!afe_priv->clk)
- return -ENOMEM;
-
- for (i = 0; i < CLK_NUM; i++) {
- afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
- if (IS_ERR(afe_priv->clk[i])) {
- dev_err(afe->dev, "%s(), devm_clk_get %s fail,\
- ret %ld\n", __func__, aud_clks[i],
- PTR_ERR(afe_priv->clk[i]));
- return PTR_ERR(afe_priv->clk[i]);
- }
- }
-
- return 0;
-}
-
-int mt79xx_afe_enable_clock(struct mtk_base_afe *afe)
-{
- struct mt79xx_afe_private *afe_priv = afe->platform_priv;
- int ret;
-
- ret = clk_prepare_enable(afe_priv->clk[CK_INFRA_AUD_BUS_CK]);
- if (ret) {
- dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
- __func__, aud_clks[CK_INFRA_AUD_BUS_CK], ret);
- goto CK_INFRA_AUD_BUS_CK_ERR;
- }
-
- ret = clk_prepare_enable(afe_priv->clk[CK_INFRA_AUD_26M_CK]);
- if (ret) {
- dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
- __func__, aud_clks[CK_INFRA_AUD_26M_CK], ret);
- goto CK_INFRA_AUD_26M_ERR;
- }
-
- ret = clk_prepare_enable(afe_priv->clk[CK_INFRA_AUD_L_CK]);
- if (ret) {
- dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n",
- __func__, aud_clks[CK_INFRA_AUD_L_CK], ret);
- goto CK_INFRA_AUD_L_CK_ERR;
- }
-
- ret = clk_prepare_enable(afe_priv->clk[CK_INFRA_AUD_AUD_CK]);
- if (ret) {
- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
- __func__, aud_clks[CK_INFRA_AUD_AUD_CK], ret);
- goto CK_INFRA_AUD_AUD_CK_ERR;
- }
-
- ret = clk_prepare_enable(afe_priv->clk[CK_INFRA_AUD_EG2_CK]);
- if (ret) {
- dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
- __func__, aud_clks[CK_INFRA_AUD_EG2_CK], ret);
- goto CK_INFRA_AUD_EG2_CK_ERR;
- }
-
- return 0;
-
-CK_INFRA_AUD_EG2_CK_ERR:
- clk_disable_unprepare(afe_priv->clk[CK_INFRA_AUD_AUD_CK]);
-CK_INFRA_AUD_AUD_CK_ERR:
- clk_disable_unprepare(afe_priv->clk[CK_INFRA_AUD_L_CK]);
-CK_INFRA_AUD_L_CK_ERR:
- clk_disable_unprepare(afe_priv->clk[CK_INFRA_AUD_26M_CK]);
-CK_INFRA_AUD_26M_ERR:
- clk_disable_unprepare(afe_priv->clk[CK_INFRA_AUD_BUS_CK]);
-CK_INFRA_AUD_BUS_CK_ERR:
- return ret;
-}
-EXPORT_SYMBOL_GPL(mt79xx_afe_enable_clock);
-
-int mt79xx_afe_disable_clock(struct mtk_base_afe *afe)
-{
- struct mt79xx_afe_private *afe_priv = afe->platform_priv;
-
- clk_disable_unprepare(afe_priv->clk[CK_INFRA_AUD_EG2_CK]);
- clk_disable_unprepare(afe_priv->clk[CK_INFRA_AUD_AUD_CK]);
- clk_disable_unprepare(afe_priv->clk[CK_INFRA_AUD_L_CK]);
- clk_disable_unprepare(afe_priv->clk[CK_INFRA_AUD_26M_CK]);
- clk_disable_unprepare(afe_priv->clk[CK_INFRA_AUD_BUS_CK]);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(mt79xx_afe_disable_clock);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-afe-clk.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-afe-clk.h
deleted file mode 100644
index 50424d8..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-afe-clk.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * mt79xx-afe-clk.h -- Mediatek 79xx afe clock ctrl definition
- *
- * Copyright (c) 2021 MediaTek Inc.
- * Author: Vic Wu <vic.wu@mediatek.com>
- */
-
-#ifndef _MT79XX_AFE_CLK_H_
-#define _MT79XX_AFE_CLK_H_
-
-struct mtk_base_afe;
-
-int mt79xx_init_clock(struct mtk_base_afe *afe);
-int mt79xx_afe_enable_clock(struct mtk_base_afe *afe);
-int mt79xx_afe_disable_clock(struct mtk_base_afe *afe);
-#endif
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-afe-common.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-afe-common.h
deleted file mode 100644
index 277d10c..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-afe-common.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * mt79xx-afe-common.h -- Mediatek 79xx audio driver definitions
- *
- * Copyright (c) 2021 MediaTek Inc.
- * Author: Vic Wu <vic.wu@mediatek.com>
- */
-
-#ifndef _MT_79XX_AFE_COMMON_H_
-#define _MT_79XX_AFE_COMMON_H_
-
-#include <sound/soc.h>
-#include <linux/list.h>
-#include <linux/regmap.h>
-#include "../common/mtk-base-afe.h"
-
-enum {
- MT79XX_MEMIF_DL1,
- MT79XX_MEMIF_VUL12,
- MT79XX_MEMIF_NUM,
- MT79XX_DAI_ETDM = MT79XX_MEMIF_NUM,
- MT79XX_DAI_NUM,
-};
-
-enum {
- MT79XX_IRQ_0,
- MT79XX_IRQ_1,
- MT79XX_IRQ_2,
- MT79XX_IRQ_NUM,
-};
-
-struct clk;
-
-struct mt79xx_afe_private {
- struct clk **clk;
-
- int pm_runtime_bypass_reg_ctl;
-
- /* dai */
- void *dai_priv[MT79XX_DAI_NUM];
-};
-
-unsigned int mt79xx_afe_rate_transform(struct device *dev,
- unsigned int rate);
-
-/* dai register */
-int mt79xx_dai_etdm_register(struct mtk_base_afe *afe);
-#endif
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-afe-pcm.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-afe-pcm.c
deleted file mode 100644
index 63162c7..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-afe-pcm.c
+++ /dev/null
@@ -1,607 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Mediatek ALSA SoC AFE platform driver for 79xx
-//
-// Copyright (c) 2021 MediaTek Inc.
-// Author: Vic Wu <vic.wu@mediatek.com>
-
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/pm_runtime.h>
-
-#include "mt79xx-afe-common.h"
-#include "mt79xx-afe-clk.h"
-#include "mt79xx-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,
-};
-
-unsigned int mt79xx_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, use %d!!!\n",
- __func__, rate, MTK_AFE_RATE_48K);
- return MTK_AFE_RATE_48K;
- }
-}
-
-static const struct snd_pcm_hardware mt79xx_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 mt79xx_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 mt79xx_afe_rate_transform(afe->dev, rate);
-}
-
-static int mt79xx_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 mt79xx_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 mt79xx_memif_dai_driver[] = {
- /* FE DAIs: memory intefaces to CPU */
- {
- .name = "DL1",
- .id = MT79XX_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 = MT79XX_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 mt79xx_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 mt79xx_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 mt79xx_afe_pcm_dai_component = {
- .name = "mt79xx-afe-pcm-dai",
-};
-
-static const struct mtk_base_memif_data memif_data[MT79XX_MEMIF_NUM] = {
- [MT79XX_MEMIF_DL1] = {
- .name = "DL1",
- .id = MT79XX_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,
- },
- [MT79XX_MEMIF_VUL12] = {
- .name = "VUL12",
- .id = MT79XX_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[MT79XX_IRQ_NUM] = {
- [MT79XX_IRQ_0] = {
- .id = MT79XX_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,
- },
- [MT79XX_IRQ_1] = {
- .id = MT79XX_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,
- },
- [MT79XX_IRQ_2] = {
- .id = MT79XX_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 mt79xx_is_volatile_reg(struct device *dev, unsigned int reg)
-{
- /* these auto-gen reg has read-only bit, so put it as volatile */
- /* volatile reg cannot be cached, so cannot be set when power 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 mt79xx_afe_regmap_config = {
- .reg_bits = 32,
- .reg_stride = 4,
- .val_bits = 32,
- .volatile_reg = mt79xx_is_volatile_reg,
- .max_register = AFE_MAX_REGISTER,
- .num_reg_defaults_raw = ((AFE_MAX_REGISTER / 4) + 1),
-};
-
-static irqreturn_t mt79xx_afe_irq_handler(int irq_id, void *dev)
-{
- struct mtk_base_afe *afe = dev;
- struct mtk_base_afe_irq *irq;
- unsigned int status;
- unsigned int status_mcu;
- unsigned int mcu_en;
- int ret;
- int i;
- 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 < MT79XX_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 mt79xx_afe_runtime_suspend(struct device *dev)
-{
- struct mtk_base_afe *afe = dev_get_drvdata(dev);
- struct mt79xx_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:
- return mt79xx_afe_disable_clock(afe);
-}
-
-static int mt79xx_afe_runtime_resume(struct device *dev)
-{
- struct mtk_base_afe *afe = dev_get_drvdata(dev);
- struct mt79xx_afe_private *afe_priv = afe->platform_priv;
- int ret;
-
- ret = mt79xx_afe_enable_clock(afe);
- if (ret)
- return ret;
-
- if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl)
- goto skip_regmap;
-
- /* 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);
-
-skip_regmap:
- return 0;
-}
-
-static int mt79xx_afe_component_probe(struct snd_soc_component *component)
-{
- return mtk_afe_add_sub_dai_control(component);
-}
-
-static const struct snd_soc_component_driver mt79xx_afe_component = {
- .name = AFE_PCM_NAME,
- .ops = &mtk_afe_pcm_ops,
- .pcm_new = mtk_afe_pcm_new,
- .pcm_free = mtk_afe_pcm_free,
- .probe = mt79xx_afe_component_probe,
-};
-
-static int mt79xx_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 = mt79xx_memif_dai_driver;
- dai->num_dai_drivers = ARRAY_SIZE(mt79xx_memif_dai_driver);
-
- dai->dapm_widgets = mt79xx_memif_widgets;
- dai->num_dapm_widgets = ARRAY_SIZE(mt79xx_memif_widgets);
- dai->dapm_routes = mt79xx_memif_routes;
- dai->num_dapm_routes = ARRAY_SIZE(mt79xx_memif_routes);
-
- return 0;
-}
-
-typedef int (*dai_register_cb)(struct mtk_base_afe *);
-static const dai_register_cb dai_register_cbs[] = {
- mt79xx_dai_etdm_register,
- mt79xx_dai_memif_register,
-};
-
-static int mt79xx_afe_pcm_dev_probe(struct platform_device *pdev)
-{
- struct mtk_base_afe *afe;
- struct mt79xx_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 = mt79xx_init_clock(afe);
- if (ret) {
- dev_err(dev, "init clock error\n");
- return ret;
- }
-
- pm_runtime_enable(dev);
-
- /* 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,
- &mt79xx_afe_regmap_config);
- if (IS_ERR(afe->regmap)) {
- ret = PTR_ERR(afe->regmap);
- goto err_pm_disable;
- }
-
- pm_runtime_put_sync(&pdev->dev);
- afe_priv->pm_runtime_bypass_reg_ctl = false;
-
- /* init memif */
- afe->memif_size = MT79XX_MEMIF_NUM;
- afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
- GFP_KERNEL);
- if (!afe->memif)
- goto err_pm_disable;
-
- 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 = MT79XX_IRQ_NUM;
- afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
- GFP_KERNEL);
- if (!afe->irqs)
- goto err_pm_disable;
-
- 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) {
- dev_err(dev, "%pOFn no irq found\n", dev->of_node);
- goto err_pm_disable;
- }
- ret = devm_request_irq(dev, irq_id, mt79xx_afe_irq_handler,
- IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);
- if (ret) {
- dev_err(dev, "could not request_irq for asys-isr\n");
- goto err_pm_disable;
- }
-
- /* 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) {
- dev_warn(afe->dev, "dai register i %d fail, ret %d\n",
- i, ret);
- goto err_pm_disable;
- }
- }
-
- /* init dai_driver and component_driver */
- ret = mtk_afe_combine_sub_dai(afe);
- if (ret) {
- dev_warn(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
- ret);
- goto err_pm_disable;
- }
-
- afe->mtk_afe_hardware = &mt79xx_afe_hardware;
- afe->memif_fs = mt79xx_memif_fs;
- afe->irq_fs = mt79xx_irq_fs;
-
- afe->runtime_resume = mt79xx_afe_runtime_resume;
- afe->runtime_suspend = mt79xx_afe_runtime_suspend;
-
- /* register component */
- ret = devm_snd_soc_register_component(&pdev->dev,
- &mt79xx_afe_component,
- NULL, 0);
- if (ret) {
- dev_warn(dev, "err_platform\n");
- goto err_pm_disable;
- }
-
- ret = devm_snd_soc_register_component(afe->dev,
- &mt79xx_afe_pcm_dai_component,
- afe->dai_drivers,
- afe->num_dai_drivers);
- if (ret) {
- dev_warn(dev, "err_dai_component\n");
- goto err_pm_disable;
- }
-
- return ret;
-
-err_pm_disable:
- pm_runtime_put_sync(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
- return ret;
-}
-
-static int mt79xx_afe_pcm_dev_remove(struct platform_device *pdev)
-{
- pm_runtime_disable(&pdev->dev);
- if (!pm_runtime_status_suspended(&pdev->dev))
- mt79xx_afe_runtime_suspend(&pdev->dev);
-
- return 0;
-}
-
-static const struct of_device_id mt79xx_afe_pcm_dt_match[] = {
- { .compatible = "mediatek,mt79xx-audio", },
- {},
-};
-MODULE_DEVICE_TABLE(of, mt79xx_afe_pcm_dt_match);
-
-static const struct dev_pm_ops mt79xx_afe_pm_ops = {
- SET_RUNTIME_PM_OPS(mt79xx_afe_runtime_suspend,
- mt79xx_afe_runtime_resume, NULL)
-};
-
-static struct platform_driver mt79xx_afe_pcm_driver = {
- .driver = {
- .name = "mt79xx-audio",
- .of_match_table = mt79xx_afe_pcm_dt_match,
- .pm = &mt79xx_afe_pm_ops,
- },
- .probe = mt79xx_afe_pcm_dev_probe,
- .remove = mt79xx_afe_pcm_dev_remove,
-};
-
-module_platform_driver(mt79xx_afe_pcm_driver);
-
-MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 79xx");
-MODULE_AUTHOR("Vic Wu <vic.wu@mediatek.com>");
-MODULE_LICENSE("GPL");
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-dai-etdm.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-dai-etdm.c
deleted file mode 100644
index 0048647..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-dai-etdm.c
+++ /dev/null
@@ -1,419 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// MediaTek ALSA SoC Audio DAI eTDM Control
-//
-// Copyright (c) 2021 MediaTek Inc.
-// Author: Vic Wu <vic.wu@mediatek.com>
-
-#include <linux/bitops.h>
-#include <linux/regmap.h>
-#include <sound/pcm_params.h>
-#include "mt79xx-afe-clk.h"
-#include "mt79xx-afe-common.h"
-#include "mt79xx-reg.h"
-
-enum {
- HOPPING_CLK = 0,
- APLL_CLK = 1,
-};
-
-enum {
- MTK_DAI_ETDM_FORMAT_I2S = 0,
- MTK_DAI_ETDM_FORMAT_DSPA = 4,
- MTK_DAI_ETDM_FORMAT_DSPB = 5,
-};
-
-enum {
- ETDM_IN5 = 2,
- ETDM_OUT5 = 10,
-};
-
-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 mt79xx_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, use %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);
-
- mt79xx_afe_enable_clock(afe);
-
- 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);
-
- 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);
-
- mt79xx_afe_disable_clock(afe);
-}
-
-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 mt79xx_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 = mt79xx_etdm_rate_transform(afe->dev, rate);
- unsigned int afe_rate = mt79xx_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 |= ETDM_BIT_LEN(bit_width);
- mask |= ETDM_WRD_LEN_MASK;
- val |= ETDM_WRD_LEN(wlen);
- mask |= ETDM_FMT_MASK;
- val |= ETDM_FMT(etdm_data->format);
- mask |= ETDM_CH_NUM_MASK;
- val |= ETDM_CH_NUM(get_etdm_ch_fixup(channels));
- mask |= RELATCH_SRC_MASK;
- val |= RELATCH_SRC(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 mt79xx_afe_private *afe_priv = afe->platform_priv;
- struct mtk_dai_etdm_priv *etdm_data;
- void *priv_data;
-
- switch (dai->id) {
- case MT79XX_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 = MT79XX_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_rates = 1,
- .symmetric_samplebits = 1,
- },
-};
-
-int mt79xx_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/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-reg.h b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-reg.h
deleted file mode 100644
index b8d2d56..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-reg.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * mt79xx-reg.h -- Mediatek 79xx audio driver reg definition
- *
- * Copyright (c) 2021 MediaTek Inc.
- * Author: Vic Wu <vic.wu@mediatek.com>
- */
-
-#ifndef _MT79XX_REG_H_
-#define _MT79XX_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(x) ((x) << 28)
-#define RELATCH_SRC_SFT 28
-#define RELATCH_SRC_MASK GENMASK(30, 28)
-#define ETDM_CH_NUM(x) (((x) - 1) << 23)
-#define ETDM_CH_NUM_SFT 23
-#define ETDM_CH_NUM_MASK GENMASK(27, 23)
-#define ETDM_WRD_LEN(x) (((x) - 1) << 16)
-#define ETDM_WRD_LEN_SFT 16
-#define ETDM_WRD_LEN_MASK GENMASK(20, 16)
-#define ETDM_BIT_LEN(x) (((x) - 1) << 11)
-#define ETDM_BIT_LEN_SFT 11
-#define ETDM_BIT_LEN_MASK GENMASK(15, 11)
-#define ETDM_FMT(x) ((x) << 6)
-#define ETDM_FMT_SFT 6
-#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) << 0)
-#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/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-wm8960.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-wm8960.c
deleted file mode 100644
index c66a117..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/sound/soc/mediatek/mt79xx/mt79xx-wm8960.c
+++ /dev/null
@@ -1,184 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * mt79xx-wm8960.c -- MT79xx WM8960 ALSA SoC machine driver
- *
- * Copyright (c) 2021 MediaTek Inc.
- * Author: Vic Wu <vic.wu@mediatek.com>
- */
-
-#include <linux/module.h>
-#include <sound/soc.h>
-
-#include "mt79xx-afe-common.h"
-
-struct mt79xx_wm8960_priv {
- struct device_node *platform_node;
- struct device_node *codec_node;
-};
-
-static const struct snd_soc_dapm_widget mt79xx_wm8960_widgets[] = {
- SND_SOC_DAPM_HP("Headphone", NULL),
- SND_SOC_DAPM_MIC("AMIC", NULL),
-};
-
-static const struct snd_kcontrol_new mt79xx_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 mt79xx_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 mt79xx_wm8960_card = {
- .name = "mt79xx-wm8960",
- .owner = THIS_MODULE,
- .dai_link = mt79xx_wm8960_dai_links,
- .num_links = ARRAY_SIZE(mt79xx_wm8960_dai_links),
- .controls = mt79xx_wm8960_controls,
- .num_controls = ARRAY_SIZE(mt79xx_wm8960_controls),
- .dapm_widgets = mt79xx_wm8960_widgets,
- .num_dapm_widgets = ARRAY_SIZE(mt79xx_wm8960_widgets),
-};
-
-static int mt79xx_wm8960_machine_probe(struct platform_device *pdev)
-{
- struct snd_soc_card *card = &mt79xx_wm8960_card;
- struct snd_soc_dai_link *dai_link;
- struct mt79xx_wm8960_priv *priv;
- int ret, i;
-
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->platform_node = of_parse_phandle(pdev->dev.of_node,
- "mediatek,platform", 0);
- if (!priv->platform_node) {
- 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;
-
- priv->codec_node = of_parse_phandle(pdev->dev.of_node,
- "mediatek,audio-codec", 0);
- if (!priv->codec_node) {
- dev_err(&pdev->dev,
- "Property 'audio-codec' missing or invalid\n");
- of_node_put(priv->platform_node);
- 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 int mt79xx_wm8960_machine_remove(struct platform_device *pdev)
-{
- struct snd_soc_card *card = platform_get_drvdata(pdev);
- struct mt79xx_wm8960_priv *priv = snd_soc_card_get_drvdata(card);
-
- of_node_put(priv->codec_node);
- of_node_put(priv->platform_node);
-
- return 0;
-}
-
-#ifdef CONFIG_OF
-static const struct of_device_id mt79xx_wm8960_machine_dt_match[] = {
- {.compatible = "mediatek,mt79xx-wm8960-machine",},
- {}
-};
-#endif
-
-static struct platform_driver mt79xx_wm8960_machine = {
- .driver = {
- .name = "mt79xx-wm8960",
-#ifdef CONFIG_OF
- .of_match_table = mt79xx_wm8960_machine_dt_match,
-#endif
- },
- .probe = mt79xx_wm8960_machine_probe,
- .remove = mt79xx_wm8960_machine_remove,
-};
-
-module_platform_driver(mt79xx_wm8960_machine);
-
-/* Module information */
-MODULE_DESCRIPTION("MT79xx WM8960 ALSA SoC machine driver");
-MODULE_AUTHOR("Vic Wu <vic.wu@mediatek.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("mt79xx wm8960 soc card");
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
index 528abb1..a31bee9 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3001-mt7622-backport-nf-hw-offload-framework-and-upstream.patch
@@ -17,13 +17,12 @@
drivers/net/ppp/pppoe.c | 24 +
include/linux/netdevice.h | 60 +
include/linux/ppp_channel.h | 3 +
- include/net/dsa.h | 10 +
include/net/flow_offload.h | 4 +
include/net/ip6_route.h | 5 +-
.../net/netfilter/ipv6/nf_conntrack_ipv6.h | 3 -
- include/net/netfilter/nf_conntrack.h | 12 +
+ include/net/netfilter/nf_conntrack.h | 14 +
include/net/netfilter/nf_conntrack_acct.h | 11 +
- include/net/netfilter/nf_flow_table.h | 266 +++-
+ include/net/netfilter/nf_flow_table.h | 268 +++-
include/net/netns/conntrack.h | 6 +
.../linux/netfilter/nf_conntrack_common.h | 9 +-
include/uapi/linux/netfilter/xt_FLOWOFFLOAD.h | 17 +
@@ -32,8 +31,7 @@
net/bridge/br_private.h | 20 +
net/bridge/br_vlan.c | 55 +
net/core/dev.c | 46 +
- net/dsa/dsa.c | 9 +
- net/dsa/slave.c | 37 +-
+ net/dsa/slave.c | 36 +-
net/ipv4/netfilter/Kconfig | 4 +-
net/ipv6/ip6_output.c | 2 +-
net/ipv6/netfilter/Kconfig | 3 +-
@@ -47,8 +45,8 @@
net/netfilter/nf_flow_table_core.c | 462 ++++---
net/netfilter/nf_flow_table_ip.c | 447 +++---
net/netfilter/nf_flow_table_offload.c | 1199 +++++++++++++++++
- net/netfilter/xt_FLOWOFFLOAD.c | 794 +++++++++++
- 43 files changed, 5005 insertions(+), 435 deletions(-)
+ net/netfilter/xt_FLOWOFFLOAD.c | 798 +++++++++++
+ 41 files changed, 4993 insertions(+), 435 deletions(-)
mode change 100644 => 100755 drivers/net/ethernet/mediatek/Makefile
mode change 100644 => 100755 drivers/net/ethernet/mediatek/mtk_eth_soc.c
mode change 100644 => 100755 drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -2157,34 +2155,6 @@
};
struct ppp_channel {
-diff --git a/include/net/dsa.h b/include/net/dsa.h
-index d29ee9e..43f65cb 100644
---- a/include/net/dsa.h
-+++ b/include/net/dsa.h
-@@ -562,6 +562,8 @@ struct dsa_switch_ops {
- struct sk_buff *skb);
- };
-
-+struct dsa_port *dsa_port_from_netdev(struct net_device *netdev);
-+
- struct dsa_switch_driver {
- struct list_head list;
- const struct dsa_switch_ops *ops;
-@@ -654,6 +656,14 @@ static inline int call_dsa_notifiers(unsigned long val, struct net_device *dev,
- #define BRCM_TAG_GET_PORT(v) ((v) >> 8)
- #define BRCM_TAG_GET_QUEUE(v) ((v) & 0xff)
-
-+#if IS_ENABLED(CONFIG_NET_DSA)
-+bool dsa_slave_dev_check(const struct net_device *dev);
-+#else
-+static inline bool dsa_slave_dev_check(const struct net_device *dev)
-+{
-+ return false;
-+}
-+#endif
-
- netdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev);
- int dsa_port_get_phy_strings(struct dsa_port *dp, uint8_t *data);
diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
index c6f7bd2..59b8736 100644
--- a/include/net/flow_offload.h
@@ -2243,6 +2213,15 @@
index 90690e3..ce0bc3e 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
+@@ -105,6 +105,8 @@ struct nf_conn {
+
+ /* Storage reserved for other modules, must be the last member */
+ union nf_conntrack_proto proto;
++
++ u16 inet6_mode;
+ };
+
+ static inline struct nf_conn *
@@ -279,6 +279,18 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct)
!nf_ct_is_dying(ct);
}
@@ -2288,7 +2267,7 @@
index 68d7fc9..feac793 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
-@@ -8,31 +8,99 @@
+@@ -8,31 +8,101 @@
#include <linux/rcupdate.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
@@ -2302,6 +2281,8 @@
+struct flow_offload;
+enum flow_offload_tuple_dir;
+
++#define CT_INET_MODE_IPV6 2
++
+struct nf_flow_key {
+ struct flow_dissector_key_meta meta;
+ struct flow_dissector_key_control control;
@@ -2970,26 +2951,6 @@
/**
* __dev_get_by_name - find a device by its name
* @net: the applicable net namespace
-diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
-index ca80f86..35a1249 100644
---- a/net/dsa/dsa.c
-+++ b/net/dsa/dsa.c
-@@ -329,6 +329,15 @@ int call_dsa_notifiers(unsigned long val, struct net_device *dev,
- }
- EXPORT_SYMBOL_GPL(call_dsa_notifiers);
-
-+struct dsa_port *dsa_port_from_netdev(struct net_device *netdev)
-+{
-+ if (!netdev || !dsa_slave_dev_check(netdev))
-+ return ERR_PTR(-ENODEV);
-+
-+ return dsa_slave_to_port(netdev);
-+}
-+EXPORT_SYMBOL_GPL(dsa_port_from_netdev);
-+
- static int __init dsa_init_module(void)
- {
- int rc;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index e2b91b3..2dfaa1e 100644
--- a/net/dsa/slave.c
@@ -3058,14 +3019,6 @@
};
static struct device_type dsa_type = {
-@@ -1499,6 +1533,7 @@ bool dsa_slave_dev_check(const struct net_device *dev)
- {
- return dev->netdev_ops == &dsa_slave_netdev_ops;
- }
-+EXPORT_SYMBOL_GPL(dsa_slave_dev_check);
-
- static int dsa_slave_changeupper(struct net_device *dev,
- struct netdev_notifier_changeupper_info *info)
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index f17b402..803b92e 100644
--- a/net/ipv4/netfilter/Kconfig
@@ -6136,7 +6089,7 @@
index 0000000..2cab008
--- /dev/null
+++ b/net/netfilter/xt_FLOWOFFLOAD.c
-@@ -0,0 +1,794 @@
+@@ -0,0 +1,798 @@
+/*
+ * Copyright (C) 2018-2021 Felix Fietkau <nbd@nbd.name>
+ *
@@ -6504,7 +6457,7 @@
+ if (!nf_is_valid_ether_device(dev))
+ goto out;
+
-+ if (ct->status & IPS_NAT_MASK) {
++ if (ct->status & IPS_NAT_MASK || ct->inet6_mode == CT_INET_MODE_IPV6) {
+ n = dst_neigh_lookup(dst_cache, daddr);
+ if (!n)
+ return -1;
@@ -6537,7 +6490,8 @@
+ unsigned char ha[ETH_ALEN];
+ int i;
+
-+ if (!(ct->status & IPS_NAT_MASK) && skb_mac_header_was_set(skb)) {
++ if (!(ct->status & IPS_NAT_MASK) && skb_mac_header_was_set(skb) &&
++ ct->inet6_mode != CT_INET_MODE_IPV6) {
+ eth = eth_hdr(skb);
+ skb_dir = CTINFO2DIR(skb_get_nfct(skb) & NFCT_INFOMASK);
+
@@ -6741,6 +6695,9 @@
+
+ dir = CTINFO2DIR(ctinfo);
+
++ if (skb->protocol == htons(ETH_P_IPV6))
++ ct->inet6_mode = CT_INET_MODE_IPV6;
++
+ if (ct->status & IPS_NAT_MASK) {
+ if (xt_flowoffload_route_nat(skb, ct, par, &route, dir, devs) < 0)
+ goto err_flow_route;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3006-add-wed-tx-support-for-netsys2.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3006-add-wed-tx-support-for-netsys2.patch
index 1cfa774..5cfedfc 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3006-add-wed-tx-support-for-netsys2.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3006-add-wed-tx-support-for-netsys2.patch
@@ -1,22 +1,35 @@
-From a0b64514c2bfe883d0128ce5bb26559c34185d90 Mon Sep 17 00:00:00 2001
+From d76914437a405265b298b7b01235a7304634c567 Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Mon, 18 Sep 2023 11:01:55 +0800
-Subject: [PATCH 07/22] add-wed-tx-support-for-mt7986
+Subject: [PATCH] add-wed-tx-support-for-mt7986
---
+ arch/arm64/boot/dts/mediatek/mt7981.dtsi | 1 +
arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 2 +
arch/arm64/boot/dts/mediatek/mt7986b.dtsi | 2 +
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 17 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 5 +
- drivers/net/ethernet/mediatek/mtk_wed.c | 496 +++++++++++++-----
+ drivers/net/ethernet/mediatek/mtk_wed.c | 498 +++++++++++++-----
drivers/net/ethernet/mediatek/mtk_wed.h | 18 +-
.../net/ethernet/mediatek/mtk_wed_debugfs.c | 3 +
drivers/net/ethernet/mediatek/mtk_wed_regs.h | 130 ++++-
include/linux/soc/mediatek/mtk_wed.h | 23 +
- 9 files changed, 547 insertions(+), 149 deletions(-)
+ 10 files changed, 549 insertions(+), 150 deletions(-)
+diff --git a/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+index e1b9b2c..3e0d2c0 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7981.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
+@@ -96,6 +96,7 @@
+ reg = <0 0x15010000 0 0x1000>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
++ mediatek,wed_pcie = <&wed_pcie>;
+ };
+
+ ap2woccif: ap2woccif@151A5000 {
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
-index 0c54e12..3ff8994 100644
+index 7e3101c..e9756bd 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
@@ -64,6 +64,7 @@
@@ -36,7 +49,7 @@
ap2woccif: ap2woccif@151A5000 {
diff --git a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
-index 2d2207f..043e509 100644
+index a780cfb..eafe314 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
@@ -64,6 +64,7 @@
@@ -55,23 +68,11 @@
};
ap2woccif: ap2woccif@151A5000 {
-diff --git a/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-index b2f53b13..d34943e7 100644
---- a/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-+++ b/arch/arm64/boot/dts/mediatek/mt7981.dtsi
-@@ -96,6 +96,7 @@
- reg = <0 0x15010000 0 0x1000>;
- interrupt-parent = <&gic>;
- interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
-+ mediatek,wed_pcie = <&wed_pcie>;
- };
-
- ap2woccif: ap2woccif@151A5000 {
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index ee5e0c6..2cab49a 100644
+index 3685926..51fe4b3 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -4968,6 +4968,7 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5091,6 +5091,7 @@ static int mtk_probe(struct platform_device *pdev)
{
struct device_node *mac_np, *mux_np;
struct mtk_eth *eth;
@@ -79,7 +80,7 @@
int err, i;
eth = devm_kzalloc(&pdev->dev, sizeof(*eth), GFP_KERNEL);
-@@ -4988,13 +4989,12 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5111,13 +5112,12 @@ static int mtk_probe(struct platform_device *pdev)
return PTR_ERR(eth->sram_base);
}
@@ -98,7 +99,7 @@
mtk_get_hwver(eth);
-@@ -5090,12 +5090,15 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5213,12 +5213,15 @@ static int mtk_probe(struct platform_device *pdev)
MTK_WDMA1_BASE
};
void __iomem *wdma;
@@ -114,12 +115,12 @@
+ mtk_wed_add_hw(np, eth, wdma, wdma_phy, i);
}
- for (i = 0; i < MTK_PDMA_IRQ_NUM; i++)
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) {
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 783166d..960b979 100644
+index b714c27..e9d88f1 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -583,8 +583,13 @@
+@@ -593,8 +593,13 @@
#define RX_DMA_SPORT_MASK 0x7
#define RX_DMA_SPORT_MASK_V2 0xf
@@ -134,7 +135,7 @@
/* QDMA descriptor txd4 */
#define TX_DMA_CHKSUM (0x7 << 29)
diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
-index ea1cbdf..0588e32 100644
+index ea1cbdf..948f013 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed.c
@@ -18,15 +18,6 @@
@@ -434,7 +435,7 @@
struct mtk_wed_hw *hw = dev->hw;
mutex_lock(&hw_lock);
-@@ -279,9 +420,12 @@ mtk_wed_detach(struct mtk_wed_device *dev)
+@@ -279,11 +420,14 @@ mtk_wed_detach(struct mtk_wed_device *dev)
mtk_wed_free_buffer(dev);
mtk_wed_free_tx_rings(dev);
@@ -448,8 +449,11 @@
+ BIT(hw->index), BIT(hw->index));
+ }
- if (!hw_list[!hw->index]->wed_dev &&
+- 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);
+
@@ -294,15 +438,87 @@ mtk_wed_detach(struct mtk_wed_device *dev)
mutex_unlock(&hw_lock);
}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3011-flow-offload-add-mtkhnat-flow-accounting.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3011-flow-offload-add-mtkhnat-flow-accounting.patch
index 3699263..c516fd6 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3011-flow-offload-add-mtkhnat-flow-accounting.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3011-flow-offload-add-mtkhnat-flow-accounting.patch
@@ -294,7 +294,7 @@
+ 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);
++ ppe_m32(ppe, MTK_PPE_MIB_CACHE_CTL, MTK_PPE_MIB_CACHE_CTL_EN, MTK_PPE_MIB_CACHE_CTL_EN);
+ }
+
return 0;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3014-update-net-bridge-for-bridger.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3014-update-net-bridge-for-bridger.patch
index b01d689..89e664f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3014-update-net-bridge-for-bridger.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3014-update-net-bridge-for-bridger.patch
@@ -14,8 +14,7 @@
net/bridge/br_vlan.c | 698 +++++++++++++++++++++++++++++++--
net/bridge/br_vlan_options.c | 346 ++++++++++++++++
net/core/rtnetlink.c | 1 +
- net/dsa/slave.c | 11 +
- 11 files changed, 1365 insertions(+), 34 deletions(-)
+ 10 files changed, 1354 insertions(+), 34 deletions(-)
create mode 100644 net/bridge/br_vlan_options.c
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
@@ -1817,30 +1816,6 @@
err = rtnl_fill_ifinfo(skb, dev, net,
RTM_NEWLINK,
NETLINK_CB(cb->skb).portid,
-diff --git a/net/dsa/slave.c b/net/dsa/slave.c
-index 2dfaa1e..a60a26c 100644
---- a/net/dsa/slave.c
-+++ b/net/dsa/slave.c
-@@ -1495,8 +1495,19 @@ int dsa_slave_create(struct dsa_port *port)
- goto out_phy;
- }
-
-+ rtnl_lock();
-+
-+ ret = netdev_upper_dev_link(master, slave_dev, NULL);
-+
-+ rtnl_unlock();
-+
-+ if (ret)
-+ goto out_unregister;
-+
- return 0;
-
-+out_unregister:
-+ unregister_netdev(slave_dev);
- out_phy:
- rtnl_lock();
- phylink_disconnect_phy(p->dp->pl);
--
2.18.0
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
index ef970de..bedf09e 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/999-3015-ethernet-update-ppe-from-netsys2-to-netsys3.patch
@@ -1,22 +1,22 @@
-From 1e2da129898cd45b4196c0aaf2de9d0e9ed46d77 Mon Sep 17 00:00:00 2001
+From 5481f7ecbd3cfffd8234bc8e952a6e07f42de76c Mon Sep 17 00:00:00 2001
From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
-Date: Wed, 25 Oct 2023 11:39:09 +0800
+Date: Tue, 21 Nov 2023 16:42:01 +0800
Subject: [PATCH 16/22] ethernet-update-ppe-from-netsys2-to-netsys3
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 14 ++++---
- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 9 +++--
- drivers/net/ethernet/mediatek/mtk_ppe.c | 31 ++++++++++++---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 ++--
+ drivers/net/ethernet/mediatek/mtk_ppe.c | 35 ++++++++++++++---
drivers/net/ethernet/mediatek/mtk_ppe.h | 38 ++++++++++++++++---
.../net/ethernet/mediatek/mtk_ppe_offload.c | 6 ++-
- drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 5 +++
- 6 files changed, 81 insertions(+), 22 deletions(-)
+ drivers/net/ethernet/mediatek/mtk_ppe_regs.h | 7 ++++
+ 6 files changed, 85 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 31c60a0..37355d9 100644
+index 850bc4f..8910d40 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2244,17 +2244,17 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+@@ -2248,17 +2248,17 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
skb_checksum_none_assert(skb);
skb->protocol = eth_type_trans(skb, netdev);
@@ -38,7 +38,7 @@
reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON_V2, trxd.rxd5);
if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) {
for (i = 0; i < eth->ppe_num; i++) {
-@@ -5262,7 +5262,8 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5290,7 +5290,8 @@ static int mtk_probe(struct platform_device *pdev)
for (i = 0; i < eth->ppe_num; i++) {
eth->ppe[i] = mtk_ppe_init(eth,
@@ -48,7 +48,7 @@
2, eth->soc->hash_way, i,
eth->soc->has_accounting);
if (!eth->ppe[i]) {
-@@ -5529,6 +5530,9 @@ static const struct mtk_soc_data mt7988_data = {
+@@ -5557,6 +5558,9 @@ static const struct mtk_soc_data mt7988_data = {
.required_clks = MT7988_CLKS_BITMAP,
.required_pctl = false,
.has_sram = true,
@@ -59,10 +59,10 @@
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma_v2),
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index 0282d25..48ecdc8 100644
+index 9c77f14..c7d36c5 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -130,9 +130,10 @@
+@@ -134,9 +134,10 @@
#define MTK_GDMA_UCS_EN BIT(20)
#define MTK_GDMA_STRP_CRC BIT(16)
#define MTK_GDMA_TO_PDMA 0x0
@@ -70,11 +70,11 @@
+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
#define MTK_GDMA_TO_PPE0 0x3333
#define MTK_GDMA_TO_PPE1 0x4444
-+#define MTK_GMAC_TO_PPE2 0xcccc
++#define MTK_GDMA_TO_PPE2 0xcccc
#else
#define MTK_GDMA_TO_PPE0 0x4444
#endif
-@@ -1972,13 +1973,13 @@ extern u32 dbg_show_level;
+@@ -1978,14 +1979,14 @@ extern u32 dbg_show_level;
static inline void mtk_set_ib1_sp(struct mtk_eth *eth, struct mtk_foe_entry *foe, u32 val)
{
@@ -91,9 +91,8 @@
return FIELD_GET(MTK_FOE_IB1_UNBIND_SRC_PORT, foe->ib1);
#else
return 0;
- #endif
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
-index 1ed1b60..5a1036f 100755
+index 8388f65..184e29d 100755
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -91,7 +91,7 @@ static int mtk_ppe_mib_wait_busy(struct mtk_ppe *ppe)
@@ -183,7 +182,16 @@
MTK_PPE_TB_CFG_INFO_SEL |
#endif
FIELD_PREP(MTK_PPE_TB_CFG_SEARCH_MISS,
-@@ -993,7 +1012,7 @@ int mtk_ppe_start(struct mtk_ppe *ppe)
+@@ -988,12 +1007,16 @@ int mtk_ppe_start(struct mtk_ppe *ppe)
+ MTK_PPE_GLO_CFG_IP4_L4_CS_DROP |
+ MTK_PPE_GLO_CFG_IP4_CS_DROP |
+ MTK_PPE_GLO_CFG_MCAST_TB_EN |
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++ MTK_PPE_GLO_CFG_CS0_PIPE_EN |
++ MTK_PPE_GLO_CFG_SRH_CACHE_FIRST_EN |
++#endif
+ MTK_PPE_GLO_CFG_FLOW_DROP_UPDATE;
+ ppe_w32(ppe, MTK_PPE_GLO_CFG, val);
ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT, 0);
@@ -308,10 +316,19 @@
ctx.dev = idev;
idev->netdev_ops->ndo_fill_receive_path(&ctx, &path);
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
-index 8d3ebe1..f8425df 100644
+index 8d3ebe1..55b9b0c 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_regs.h
-@@ -155,9 +155,14 @@ enum {
+@@ -18,6 +18,8 @@
+ #define MTK_PPE_GLO_CFG_UDP_LITE_EN BIT(10)
+ #define MTK_PPE_GLO_CFG_UDP_LEN_DROP BIT(11)
+ #define MTK_PPE_GLO_CFG_MCAST_ENTRIES GNEMASK(13, 12)
++#define MTK_PPE_GLO_CFG_CS0_PIPE_EN BIT(29)
++#define MTK_PPE_GLO_CFG_SRH_CACHE_FIRST_EN BIT(30)
+ #define MTK_PPE_GLO_CFG_BUSY BIT(31)
+
+ #define MTK_PPE_FLOW_CFG 0x204
+@@ -155,9 +157,14 @@ enum {
#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)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
index 33046cd..20984c3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7986.cfg
@@ -288,6 +288,7 @@
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_IRQ_WORK=y
CONFIG_JUMP_LABEL=y
+# CONFIG_LEDS_CLASS_MULTICOLOR is not set
# CONFIG_LEDS_UBNT_LEDBAR is not set
CONFIG_LIBFDT=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
@@ -549,3 +550,6 @@
# CONFIG_FUNCTION_ERROR_INJECTION is not set
CONFIG_RICHTEK_RTQ6056=y
CONFIG_ZTS8032=y
+# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set
+# CONFIG_CRYPTO_CAVP_TEST is not set
+# CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG is not set
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
index 06ec24b..a36a0db 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
@@ -260,6 +260,7 @@
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_IRQ_WORK=y
CONFIG_JUMP_LABEL=y
+# CONFIG_LEDS_CLASS_MULTICOLOR is not set
# CONFIG_LEDS_UBNT_LEDBAR is not set
CONFIG_LIBFDT=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
@@ -520,3 +521,6 @@
# CONFIG_FUNCTION_ERROR_INJECTION is not set
CONFIG_RICHTEK_RTQ6056=y
CONFIG_ZTS8032=y
+# CONFIG_CRYPTO_USER_API_RNG_CAVP is not set
+# CONFIG_CRYPTO_CAVP_TEST is not set
+# CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG is not set
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-1022-backport-linux-6.2-xfrm-packet-mode.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-1022-v6.2-xfrm-packet-mode.patch
similarity index 97%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-1022-backport-linux-6.2-xfrm-packet-mode.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-1022-v6.2-xfrm-packet-mode.patch
index 9eb9347..57817da 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-1022-backport-linux-6.2-xfrm-packet-mode.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-1022-v6.2-xfrm-packet-mode.patch
@@ -644,7 +644,7 @@
static void xfrm_hash_transfer(struct hlist_head *list,
struct hlist_head *ndsttable,
struct hlist_head *nsrctable,
-@@ -93,18 +112,20 @@ static void xfrm_hash_transfer(struct hl
+@@ -93,18 +112,19 @@ static void xfrm_hash_transfer(struct hl
h = __xfrm_dst_hash(&x->id.daddr, &x->props.saddr,
x->props.reqid, x->props.family,
nhashmask);
@@ -661,13 +661,13 @@
h = __xfrm_spi_hash(&x->id.daddr, x->id.spi,
x->id.proto, x->props.family,
nhashmask);
- hlist_add_head_rcu(&x->byspi, nspitable + h);
+- hlist_add_head_rcu(&x->byspi, nspitable + h);
+ XFRM_STATE_INSERT(byspi, &x->byspi, nspitable + h,
+ x->xso.type);
}
}
}
-@@ -527,6 +548,8 @@ static enum hrtimer_restart xfrm_timer_h
+@@ -527,6 +547,8 @@ static enum hrtimer_restart xfrm_timer_h
int err = 0;
spin_lock(&x->lock);
@@ -676,7 +676,7 @@
if (x->km.state == XFRM_STATE_DEAD)
goto out;
if (x->km.state == XFRM_STATE_EXPIRED)
-@@ -923,6 +946,49 @@ xfrm_init_tempstate(struct xfrm_state *x
+@@ -923,6 +945,49 @@ xfrm_init_tempstate(struct xfrm_state *x
x->props.family = tmpl->encap_family;
}
@@ -726,7 +726,7 @@
static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark,
const xfrm_address_t *daddr,
__be32 spi, u8 proto,
-@@ -1062,6 +1128,23 @@ xfrm_state_find(const xfrm_address_t *da
+@@ -1062,6 +1127,23 @@ xfrm_state_find(const xfrm_address_t *da
rcu_read_lock();
h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family);
hlist_for_each_entry_rcu(x, net->xfrm.state_bydst + h, bydst) {
@@ -750,7 +750,7 @@
if (x->props.family == encap_family &&
x->props.reqid == tmpl->reqid &&
(mark & x->mark.m) == x->mark.v &&
-@@ -1079,6 +1162,23 @@ xfrm_state_find(const xfrm_address_t *da
+@@ -1079,6 +1161,23 @@ xfrm_state_find(const xfrm_address_t *da
h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, encap_family);
hlist_for_each_entry_rcu(x, net->xfrm.state_bydst + h_wildcard, bydst) {
@@ -774,7 +774,7 @@
if (x->props.family == encap_family &&
x->props.reqid == tmpl->reqid &&
(mark & x->mark.m) == x->mark.v &&
-@@ -1096,8 +1196,10 @@ found:
+@@ -1096,8 +1195,10 @@ found:
x = best;
if (!x && !error && !acquire_in_progress) {
if (tmpl->id.spi &&
@@ -787,7 +787,7 @@
to_put = x0;
error = -EEXIST;
goto out;
-@@ -1131,17 +1233,42 @@ found:
+@@ -1131,17 +1232,42 @@ found:
x = NULL;
goto out;
}
@@ -834,7 +834,7 @@
}
x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
hrtimer_start(&x->mtimer,
-@@ -1151,6 +1278,16 @@ found:
+@@ -1151,6 +1277,16 @@ found:
xfrm_hash_grow_check(net, x->bydst.next != NULL);
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
} else {
@@ -851,7 +851,7 @@
x->km.state = XFRM_STATE_DEAD;
to_put = x;
x = NULL;
-@@ -1246,16 +1383,19 @@ static void __xfrm_state_insert(struct x
+@@ -1246,16 +1382,19 @@ static void __xfrm_state_insert(struct x
h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr,
x->props.reqid, x->props.family);
@@ -874,7 +874,7 @@
}
hrtimer_start(&x->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL_SOFT);
-@@ -1369,9 +1509,11 @@ static struct xfrm_state *__find_acq_cor
+@@ -1369,9 +1508,11 @@ static struct xfrm_state *__find_acq_cor
ktime_set(net->xfrm.sysctl_acq_expires, 0),
HRTIMER_MODE_REL_SOFT);
list_add(&x->km.all, &net->xfrm.state_all);
@@ -888,7 +888,7 @@
net->xfrm.state_num++;
-@@ -1742,6 +1884,8 @@ EXPORT_SYMBOL(xfrm_state_update);
+@@ -1742,6 +1883,8 @@ EXPORT_SYMBOL(xfrm_state_update);
int xfrm_state_check_expire(struct xfrm_state *x)
{
@@ -897,7 +897,7 @@
if (!x->curlft.use_time)
x->curlft.use_time = ktime_get_real_seconds();
-@@ -2043,7 +2187,8 @@ int xfrm_alloc_spi(struct xfrm_state *x,
+@@ -2043,7 +2186,8 @@ int xfrm_alloc_spi(struct xfrm_state *x,
spin_lock_bh(&net->xfrm.xfrm_state_lock);
x->id.spi = newspi;
h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2728-xfrm-extend-packet-mode-to-support-esp-tunnel-mode.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2728-xfrm-extend-packet-mode-to-support-esp-tunnel-mode.patch
index d41c0f3..17ae470 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2728-xfrm-extend-packet-mode-to-support-esp-tunnel-mode.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-2728-xfrm-extend-packet-mode-to-support-esp-tunnel-mode.patch
@@ -33,3 +33,31 @@
if (skb_is_gso(skb))
return xfrm_output_gso(net, sk, skb);
}
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -3703,6 +3703,10 @@ int __xfrm_policy_check(struct sock *sk,
+ }
+ }
+ #endif
++ /* Inbound HW offload packets, pass the check directly */
++ if (pol->xdo.type == XFRM_DEV_OFFLOAD_PACKET &&
++ (pol->xdo.dir == XFRM_DEV_OFFLOAD_IN || pol->xdo.dir == XFRM_DEV_OFFLOAD_FWD))
++ return 1;
+
+ if (pol->action == XFRM_POLICY_ALLOW) {
+ static struct sec_path dummy;
+@@ -3712,6 +3716,14 @@ int __xfrm_policy_check(struct sock *sk,
+ int ti = 0;
+ int i, k;
+
++ /* Strongswan install FWD policy for inbound HW offload
++ * packets. But cannot find corresponding packet offload
++ * state here and will be drop. So, we bypass following
++ * check for FWD policy with acction allow.
++ */
++ if (dir == XFRM_POLICY_FWD)
++ return 1;
++
+ sp = skb_sec_path(skb);
+ if (!sp)
+ sp = &dummy;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4100-mtk-tunnel-offload-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4100-mtk-tunnel-offload-support.patch
index 299c7b4..6c26c22 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4100-mtk-tunnel-offload-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4100-mtk-tunnel-offload-support.patch
@@ -1,489 +1,488 @@
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -245,6 +245,9 @@ static const char * const mtk_clks_source_name[] = {
- "top_netsys_warp_sel",
- };
-
-+struct net_device *(*mtk_get_tnl_dev)(int tnl_idx) = NULL;
-+EXPORT_SYMBOL(mtk_get_tnl_dev);
-+
- void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
- {
- __raw_writel(val, eth->base + reg);
-@@ -2186,6 +2189,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
- u64 addr64 = 0;
- u8 *data, *new_data;
- struct mtk_rx_dma_v2 *rxd, trxd;
-+ int tnl_idx = 0;
- int done = 0;
-
- if (unlikely(!ring))
-@@ -2229,11 +2233,20 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
- 0 : RX_DMA_GET_SPORT(trxd.rxd4) - 1;
- }
-
-- if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
-- !eth->netdev[mac]))
-- goto release_desc;
-+ tnl_idx = RX_DMA_GET_TOPS_CRSN(trxd.rxd6);
-+ if (mtk_get_tnl_dev && tnl_idx) {
-+ netdev = mtk_get_tnl_dev(tnl_idx);
-+ if (unlikely(IS_ERR(netdev)))
-+ netdev = NULL;
-+ }
-
-- netdev = eth->netdev[mac];
-+ if (!netdev) {
-+ if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
-+ !eth->netdev[mac]))
-+ goto release_desc;
-+
-+ netdev = eth->netdev[mac];
-+ }
-
- if (unlikely(test_bit(MTK_RESETTING, ð->state)))
- goto release_desc;
-@@ -2318,6 +2331,8 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
- skb_hnat_alg(skb) = 0;
- skb_hnat_filled(skb) = 0;
- skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
-+ skb_hnat_set_tops(skb, 0);
-+ skb_hnat_set_is_decap(skb, 0);
-
- if (skb_hnat_reason(skb) == HIT_BIND_FORCE_TO_CPU) {
- trace_printk("[%s] reason=0x%x(force to CPU) from WAN to Ext\n",
---- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
-+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
-@@ -43,6 +43,12 @@ void (*ppe_dev_register_hook)(struct net_device *dev) = NULL;
- EXPORT_SYMBOL(ppe_dev_register_hook);
- void (*ppe_dev_unregister_hook)(struct net_device *dev) = NULL;
- EXPORT_SYMBOL(ppe_dev_unregister_hook);
-+int (*mtk_tnl_encap_offload)(struct sk_buff *skb) = NULL;
-+EXPORT_SYMBOL(mtk_tnl_encap_offload);
-+int (*mtk_tnl_decap_offload)(struct sk_buff *skb) = NULL;
-+EXPORT_SYMBOL(mtk_tnl_decap_offload);
-+bool (*mtk_tnl_decap_offloadable)(struct sk_buff *skb) = NULL;
-+EXPORT_SYMBOL(mtk_tnl_decap_offloadable);
-
- static void hnat_sma_build_entry(struct timer_list *t)
- {
-@@ -53,6 +59,16 @@ static void hnat_sma_build_entry(struct timer_list *t)
- SMA, SMA_FWD_CPU_BUILD_ENTRY);
- }
-
-+struct foe_entry *hnat_get_foe_entry(u32 ppe_id, u32 index)
-+{
-+ if (index == 0x7fff || index >= hnat_priv->foe_etry_num
-+ || ppe_id >= CFG_PPE_NUM)
-+ return ERR_PTR(-EINVAL);
-+
-+ return &hnat_priv->foe_table_cpu[ppe_id][index];
-+}
-+EXPORT_SYMBOL(hnat_get_foe_entry);
-+
- void hnat_cache_ebl(int enable)
- {
- int i;
-@@ -63,6 +79,7 @@ void hnat_cache_ebl(int enable)
- cr_set_field(hnat_priv->ppe_base[i] + PPE_CAH_CTRL, CAH_EN, enable);
- }
- }
-+EXPORT_SYMBOL(hnat_cache_ebl);
-
- static void hnat_reset_timestamp(struct timer_list *t)
- {
---- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
-+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
-@@ -1133,6 +1133,8 @@ enum FoeIpAct {
- #define NR_WDMA1_PORT 9
- #define NR_WDMA2_PORT 13
- #define NR_GMAC3_PORT 15
-+#define NR_TDMA_TPORT 4
-+#define NR_TDMA_QDMA_TPORT 5
- #define LAN_DEV_NAME hnat_priv->lan
- #define LAN2_DEV_NAME hnat_priv->lan2
- #define IS_WAN(dev) \
-@@ -1256,6 +1258,8 @@ static inline bool hnat_dsa_is_enable(struct mtk_hnat *priv)
- }
- #endif
-
-+struct foe_entry *hnat_get_foe_entry(u32 ppe_id, u32 index);
-+
- void hnat_deinit_debugfs(struct mtk_hnat *h);
- int hnat_init_debugfs(struct mtk_hnat *h);
- int hnat_register_nf_hooks(void);
-@@ -1272,6 +1276,9 @@ extern int qos_ul_toggle;
- extern int hook_toggle;
- extern int mape_toggle;
- extern int qos_toggle;
-+extern int (*mtk_tnl_encap_offload)(struct sk_buff *skb);
-+extern int (*mtk_tnl_decap_offload)(struct sk_buff *skb);
-+extern bool (*mtk_tnl_decap_offloadable)(struct sk_buff *skb);
-
- int ext_if_add(struct extdev_entry *ext_entry);
- int ext_if_del(struct extdev_entry *ext_entry);
---- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
-+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
-@@ -726,10 +726,14 @@ static unsigned int is_ppe_support_type(struct sk_buff *skb)
- case ETH_P_IP:
- iph = ip_hdr(skb);
-
-- /* do not accelerate non tcp/udp traffic */
-- if ((iph->protocol == IPPROTO_TCP) ||
-+ if (mtk_tnl_decap_offloadable && mtk_tnl_decap_offloadable(skb)) {
-+ /* tunnel protocol is offloadable */
-+ skb_hnat_set_is_decap(skb, 1);
-+ return 1;
-+ } else if ((iph->protocol == IPPROTO_TCP) ||
- (iph->protocol == IPPROTO_UDP) ||
- (iph->protocol == IPPROTO_IPV6)) {
-+ /* do not accelerate non tcp/udp traffic */
- return 1;
- }
-
-@@ -846,6 +850,13 @@ mtk_hnat_ipv4_nf_pre_routing(void *priv, struct sk_buff *skb,
-
- hnat_set_head_frags(state, skb, -1, hnat_set_iif);
-
-+ if (skb_hnat_tops(skb) && skb_hnat_is_decap(skb)
-+ && is_magic_tag_valid(skb)
-+ && skb_hnat_iface(skb) == FOE_MAGIC_GE_VIRTUAL
-+ && mtk_tnl_decap_offload && mtk_tnl_decap_offload(skb)) {
-+ return NF_ACCEPT;
-+ }
-+
- /*
- * Avoid mistakenly binding of outer IP, ports in SW L2TP decap flow.
- * In pre-routing, if dev is virtual iface, TOPS module is not loaded,
-@@ -921,6 +932,13 @@ mtk_hnat_br_nf_local_in(void *priv, struct sk_buff *skb,
-
- hnat_set_head_frags(state, skb, -1, hnat_set_iif);
-
-+ if (skb_hnat_tops(skb) && skb_hnat_is_decap(skb)
-+ && is_magic_tag_valid(skb)
-+ && skb_hnat_iface(skb) == FOE_MAGIC_GE_VIRTUAL
-+ && mtk_tnl_decap_offload && mtk_tnl_decap_offload(skb)) {
-+ return NF_ACCEPT;
-+ }
-+
- pre_routing_print(skb, state->in, state->out, __func__);
-
- if (unlikely(debug_level >= 7)) {
-@@ -1073,9 +1091,22 @@ static unsigned int hnat_ipv4_get_nexthop(struct sk_buff *skb,
- return -1;
- }
-
-+ /*
-+ * if this packet is a tunnel packet and is about to construct
-+ * outer header, we must update its outer mac header pointer
-+ * before filling outer mac or it may screw up inner mac
-+ */
-+ if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) {
-+ skb_push(skb, sizeof(struct ethhdr));
-+ skb_reset_mac_header(skb);
-+ }
-+
- memcpy(eth_hdr(skb)->h_dest, neigh->ha, ETH_ALEN);
- memcpy(eth_hdr(skb)->h_source, out->dev_addr, ETH_ALEN);
-
-+ if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb))
-+ skb_pull(skb, sizeof(struct ethhdr));
-+
- rcu_read_unlock_bh();
-
- return 0;
-@@ -1201,6 +1232,81 @@ static struct ethhdr *get_ipv6_ipip_ethhdr(struct sk_buff *skb,
- return eth;
- }
-
-+static inline void hnat_get_filled_unbind_entry(struct sk_buff *skb,
-+ struct foe_entry *entry)
-+{
-+ if (unlikely(!skb || !entry))
-+ return;
-+
-+ memcpy(entry,
-+ &hnat_priv->foe_table_cpu[skb_hnat_ppe(skb)][skb_hnat_entry(skb)],
-+ sizeof(*entry));
-+
-+#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
-+ entry->bfib1.mc = 0;
-+#endif /* defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3) */
-+ entry->bfib1.ka = 0;
-+ entry->bfib1.vlan_layer = 0;
-+ entry->bfib1.psn = 0;
-+ entry->bfib1.vpm = 0;
-+ entry->bfib1.ps = 0;
-+}
-+
-+static inline void hnat_qos_tnl(u32 id, const struct net_device *dev)
-+{
-+ u32 cfg;
-+ u32 max_man = 0;
-+ u32 max_exp = 0;
-+ const struct mtk_mac *mac;
-+
-+ if (!dev)
-+ return;
-+ mac = netdev_priv(dev);
-+
-+ switch (mac->speed) {
-+ case SPEED_100:
-+ case SPEED_1000:
-+ case SPEED_2500:
-+ case SPEED_5000:
-+ case SPEED_10000:
-+ max_man = mac->speed / SPEED_100;
-+ max_exp = 5;
-+ break;
-+ default:
-+ return;
-+ }
-+
-+ cfg = QTX_SCH_MIN_RATE_EN | QTX_SCH_MAX_RATE_EN;
-+ cfg |= (1 << QTX_SCH_MIN_RATE_MAN_OFFSET) |
-+ (4 << QTX_SCH_MIN_RATE_EXP_OFFSET) |
-+ (max_man << QTX_SCH_MAX_RATE_MAN_OFFSET) |
-+ (max_exp << QTX_SCH_MAX_RATE_EXP_OFFSET) |
-+ (4 << QTX_SCH_MAX_RATE_WGHT_OFFSET);
-+ writel(cfg, hnat_priv->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
-+}
-+
-+static inline void hnat_fill_offload_engine_entry(struct sk_buff *skb,
-+ struct foe_entry *entry,
-+ const struct net_device *dev)
-+{
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-+ if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) {
-+ /*
-+ * if skb_hnat_tops(skb) is setup for encapsulation,
-+ * we fill in hnat tport and tops_entry for tunnel encapsulation
-+ * offloading
-+ */
-+ entry->ipv4_hnapt.tport_id = NR_TDMA_QDMA_TPORT;
-+ entry->ipv4_hnapt.tops_entry = skb_hnat_tops(skb);
-+ } else {
-+ return;
-+ }
-+
-+ entry->ipv4_hnapt.iblk2.qid = 12; /* offload engine use QID 12 */
-+ hnat_qos_tnl(12, dev); /* set rate limit to line rate */
-+#endif /* defined(CONFIG_MEDIATEK_NETSYS_V3) */
-+}
-+
- static unsigned int skb_to_hnat_info(struct sk_buff *skb,
- const struct net_device *dev,
- struct foe_entry *foe,
-@@ -1237,6 +1343,11 @@ static unsigned int skb_to_hnat_info(struct sk_buff *skb,
- if (whnat && is_hnat_pre_filled(foe))
- return 0;
-
-+ if (skb_hnat_tops(skb) && !(hw_path->flags & FLOW_OFFLOAD_PATH_TNL)) {
-+ hnat_get_filled_unbind_entry(skb, &entry);
-+ goto hnat_entry_bind;
-+ }
-+
- entry.bfib1.pkt_type = foe->udib1.pkt_type; /* Get packte type state*/
- entry.bfib1.state = foe->udib1.state;
-
-@@ -1679,6 +1790,10 @@ static unsigned int skb_to_hnat_info(struct sk_buff *skb,
- /* Fill Layer2 Info.*/
- entry = ppe_fill_L2_info(eth, entry, hw_path);
-
-+ if (skb_hnat_tops(skb) && hw_path->flags & FLOW_OFFLOAD_PATH_TNL)
-+ goto hnat_entry_skip_bind;
-+
-+hnat_entry_bind:
- /* Fill Info Blk*/
- entry = ppe_fill_info_blk(eth, entry, hw_path);
-
-@@ -1879,7 +1994,20 @@ static unsigned int skb_to_hnat_info(struct sk_buff *skb,
- entry.ipv6_5t_route.act_dp |= UDF_HNAT_PRE_FILLED;
- }
-
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-+ hnat_fill_offload_engine_entry(skb, &entry, dev);
-+#endif
-+
-+hnat_entry_skip_bind:
- wmb();
-+
-+ /*
-+ * final check before we write BIND info.
-+ * If this entry is already bound, we should not modify it right now
-+ */
-+ if (entry_hnat_is_bound(foe))
-+ return 0;
-+
- memcpy(foe, &entry, sizeof(entry));
- /*reset statistic for this entry*/
- if (hnat_priv->data->per_flow_accounting &&
-@@ -1951,6 +2079,12 @@ int mtk_sw_nat_hook_tx(struct sk_buff *skb, int gmac_no)
- switch ((int)entry.bfib1.pkt_type) {
- case IPV4_HNAPT:
- case IPV4_HNAT:
-+ /*
-+ * skip if packet is an encap tnl packet or it may
-+ * screw up inner mac header
-+ */
-+ if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb))
-+ break;
- entry.ipv4_hnapt.smac_hi = swab32(*((u32 *)eth->h_source));
- entry.ipv4_hnapt.smac_lo = swab16(*((u16 *)ð->h_source[4]));
- break;
-@@ -2112,6 +2246,10 @@ int mtk_sw_nat_hook_tx(struct sk_buff *skb, int gmac_no)
- entry.ipv6_5t_route.iblk2.dp = gmac_no;
- }
-
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-+ hnat_fill_offload_engine_entry(skb, &entry, NULL);
-+#endif
-+
- entry.bfib1.ttl = 1;
- entry.bfib1.state = BIND;
-
-@@ -2187,6 +2325,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *skb)
- }
-
- skb_hnat_alg(skb) = 0;
-+ skb_hnat_set_tops(skb, 0);
- skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
-
- if (skb_hnat_iface(skb) == FOE_MAGIC_WED0)
-@@ -2636,6 +2775,7 @@ static unsigned int mtk_hnat_nf_post_routing(
- struct flow_offload_hw_path hw_path = { .dev = (struct net_device*)out,
- .virt_dev = (struct net_device*)out };
- const struct net_device *arp_dev = out;
-+ bool is_virt_dev = false;
-
- if (xlat_toggle && !mtk_464xlat_post_process(skb, out))
- return 0;
-@@ -2652,10 +2792,29 @@ static unsigned int mtk_hnat_nf_post_routing(
-
- if (out->netdev_ops->ndo_flow_offload_check) {
- out->netdev_ops->ndo_flow_offload_check(&hw_path);
-+
- out = (IS_GMAC1_MODE) ? hw_path.virt_dev : hw_path.dev;
-+ if (hw_path.flags & FLOW_OFFLOAD_PATH_TNL && mtk_tnl_encap_offload) {
-+ if (ntohs(skb->protocol) == ETH_P_IP
-+ && ip_hdr(skb)->protocol == IPPROTO_TCP) {
-+ skb_hnat_set_tops(skb, hw_path.tnl_type + 1);
-+ } else {
-+ /*
-+ * we are not support protocols other than IPv4 TCP
-+ * for tunnel protocol offload yet
-+ */
-+ skb_hnat_alg(skb) = 1;
-+ return 0;
-+ }
-+ }
- }
-
- if (!IS_LAN_GRP(out) && !IS_WAN(out) && !IS_EXT(out))
-+ is_virt_dev = true;
-+
-+ if (is_virt_dev
-+ && !(skb_hnat_tops(skb) && skb_hnat_is_encap(skb)
-+ && (hw_path.flags & FLOW_OFFLOAD_PATH_TNL)))
- return 0;
-
- trace_printk("[%s] case hit, %x-->%s, reason=%x\n", __func__,
-@@ -2675,9 +2834,18 @@ static unsigned int mtk_hnat_nf_post_routing(
- if (fn && !mtk_hnat_accel_type(skb))
- break;
-
-- if (fn && fn(skb, arp_dev, &hw_path))
-+ if (!is_virt_dev && fn && fn(skb, arp_dev, &hw_path))
- break;
-
-+ /* skb_hnat_tops(skb) is updated in mtk_tnl_offload() */
-+ if (skb_hnat_tops(skb)) {
-+ if (skb_hnat_is_encap(skb) && !is_virt_dev
-+ && mtk_tnl_encap_offload && mtk_tnl_encap_offload(skb))
-+ break;
-+ if (skb_hnat_is_decap(skb))
-+ break;
-+ }
-+
- spin_lock(&hnat_priv->entry_lock);
- skb_to_hnat_info(skb, out, entry, &hw_path);
- spin_unlock(&hnat_priv->entry_lock);
-@@ -2951,7 +3119,7 @@ mtk_hnat_ipv4_nf_local_out(void *priv, struct sk_buff *skb,
- if (iph->protocol == IPPROTO_IPV6) {
- entry->udib1.pkt_type = IPV6_6RD;
- hnat_set_head_frags(state, skb, 0, hnat_set_alg);
-- } else {
-+ } else if (!skb_hnat_tops(skb)) {
- hnat_set_head_frags(state, skb, 1, hnat_set_alg);
- }
-
---- a/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
-+++ b/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
-@@ -44,7 +44,9 @@ struct hnat_desc {
- u32 is_sp : 1;
- u32 hf : 1;
- u32 amsdu : 1;
-- u32 resv3 : 19;
-+ u32 tops : 6;
-+ u32 is_decap : 1;
-+ u32 resv3 : 12;
- u32 magic_tag_protect : 16;
- } __packed;
- #elif defined(CONFIG_MEDIATEK_NETSYS_RX_V2)
-@@ -91,6 +93,19 @@ struct hnat_desc {
- ((((skb_headroom(skb) >= FOE_INFO_LEN) ? 1 : 0)))
-
- #define skb_hnat_info(skb) ((struct hnat_desc *)(skb->head))
-+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
-+#define skb_hnat_tops(skb) (((struct hnat_desc *)((skb)->head))->tops)
-+#define skb_hnat_is_decap(skb) (((struct hnat_desc *)((skb)->head))->is_decap)
-+#define skb_hnat_is_encap(skb) (!skb_hnat_is_decap(skb))
-+#define skb_hnat_set_tops(skb, tops) ((skb_hnat_tops(skb)) = (tops))
-+#define skb_hnat_set_is_decap(skb, is_decap) ((skb_hnat_is_decap(skb)) = (is_decap))
-+#else /* !defined(CONFIG_MEDIATEK_NETSYS_V3) */
-+#define skb_hnat_tops(skb) (0)
-+#define skb_hnat_is_decap(skb) (0)
-+#define skb_hnat_is_encap(skb) (0)
-+#define skb_hnat_set_tops(skb, tops)
-+#define skb_hnat_set_is_decap(skb, is_decap)
-+#endif /* defined(CONFIG_MEDIATEK_NETSYS_V3) */
- #define skb_hnat_magic(skb) (((struct hnat_desc *)(skb->head))->magic)
- #define skb_hnat_reason(skb) (((struct hnat_desc *)(skb->head))->crsn)
- #define skb_hnat_entry(skb) (((struct hnat_desc *)(skb->head))->entry)
---- a/include/net/netfilter/nf_flow_table.h
-+++ b/include/net/netfilter/nf_flow_table.h
-@@ -98,10 +98,22 @@ struct flow_offload {
- #define FLOW_OFFLOAD_PATH_6RD BIT(5)
- #define FLOW_OFFLOAD_PATH_TNL BIT(6)
-
-+enum flow_offload_tnl {
-+ FLOW_OFFLOAD_TNL_GRETAP,
-+ FLOW_OFFLOAD_TNL_PPTP,
-+ FLOW_OFFLOAD_TNL_IP_L2TP,
-+ FLOW_OFFLOAD_TNL_UDP_L2TP_CTRL,
-+ FLOW_OFFLOAD_TNL_UDP_L2TP_DATA,
-+ FLOW_OFFLOAD_VXLAN,
-+ FLOW_OFFLOAD_NATT,
-+ __FLOW_OFFLOAD_MAX,
-+};
-+
- struct flow_offload_hw_path {
- struct net_device *dev;
- struct net_device *virt_dev;
- u32 flags;
-+ u32 tnl_type;
-
- u8 eth_src[ETH_ALEN];
- u8 eth_dest[ETH_ALEN];
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -1904,6 +1904,9 @@ extern const struct of_device_id of_mtk_match[];
- extern u32 mtk_hwlro_stats_ebl;
- extern u32 dbg_show_level;
-
-+/* tunnel offload related */
-+extern struct net_device *(*mtk_get_tnl_dev)(int tnl_idx);
-+
- /* read the hardware status register */
- void mtk_stats_update_mac(struct mtk_mac *mac);
-
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -245,6 +245,9 @@ static const char * const mtk_clks_sourc
+ "top_netsys_warp_sel",
+ };
+
++struct net_device *(*mtk_get_tnl_dev)(int tnl_idx) = NULL;
++EXPORT_SYMBOL(mtk_get_tnl_dev);
++
+ void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
+ {
+ __raw_writel(val, eth->base + reg);
+@@ -2168,6 +2171,7 @@ static int mtk_poll_rx(struct napi_struc
+ u64 addr64 = 0;
+ u8 *data, *new_data;
+ struct mtk_rx_dma_v2 *rxd, trxd;
++ int tnl_idx = 0;
+ int done = 0;
+
+ if (unlikely(!ring))
+@@ -2205,11 +2209,20 @@ static int mtk_poll_rx(struct napi_struc
+ 0 : RX_DMA_GET_SPORT(trxd.rxd4) - 1;
+ }
+
+- if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
+- !eth->netdev[mac]))
+- goto release_desc;
++ tnl_idx = RX_DMA_GET_TOPS_CRSN(trxd.rxd6);
++ if (mtk_get_tnl_dev && tnl_idx) {
++ netdev = mtk_get_tnl_dev(tnl_idx);
++ if (unlikely(IS_ERR(netdev)))
++ netdev = NULL;
++ }
+
+- netdev = eth->netdev[mac];
++ if (!netdev) {
++ if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
++ !eth->netdev[mac]))
++ goto release_desc;
++
++ netdev = eth->netdev[mac];
++ }
+
+ if (unlikely(test_bit(MTK_RESETTING, ð->state)))
+ goto release_desc;
+@@ -2294,6 +2307,8 @@ static int mtk_poll_rx(struct napi_struc
+ skb_hnat_alg(skb) = 0;
+ skb_hnat_filled(skb) = 0;
+ skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
++ skb_hnat_set_tops(skb, 0);
++ skb_hnat_set_is_decap(skb, 0);
+
+ if (skb_hnat_reason(skb) == HIT_BIND_FORCE_TO_CPU) {
+ trace_printk("[%s] reason=0x%x(force to CPU) from WAN to Ext\n",
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -1915,6 +1915,9 @@ extern const struct of_device_id of_mtk_
+ extern u32 mtk_hwlro_stats_ebl;
+ extern u32 dbg_show_level;
+
++/* tunnel offload related */
++extern struct net_device *(*mtk_get_tnl_dev)(int tnl_idx);
++
+ /* read the hardware status register */
+ void mtk_stats_update_mac(struct mtk_mac *mac);
+
+--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
+@@ -43,6 +43,12 @@ void (*ppe_dev_register_hook)(struct net
+ EXPORT_SYMBOL(ppe_dev_register_hook);
+ void (*ppe_dev_unregister_hook)(struct net_device *dev) = NULL;
+ EXPORT_SYMBOL(ppe_dev_unregister_hook);
++int (*mtk_tnl_encap_offload)(struct sk_buff *skb) = NULL;
++EXPORT_SYMBOL(mtk_tnl_encap_offload);
++int (*mtk_tnl_decap_offload)(struct sk_buff *skb) = NULL;
++EXPORT_SYMBOL(mtk_tnl_decap_offload);
++bool (*mtk_tnl_decap_offloadable)(struct sk_buff *skb) = NULL;
++EXPORT_SYMBOL(mtk_tnl_decap_offloadable);
+
+ static void hnat_sma_build_entry(struct timer_list *t)
+ {
+@@ -53,6 +59,16 @@ static void hnat_sma_build_entry(struct
+ SMA, SMA_FWD_CPU_BUILD_ENTRY);
+ }
+
++struct foe_entry *hnat_get_foe_entry(u32 ppe_id, u32 index)
++{
++ if (index == 0x7fff || index >= hnat_priv->foe_etry_num
++ || ppe_id >= CFG_PPE_NUM)
++ return ERR_PTR(-EINVAL);
++
++ return &hnat_priv->foe_table_cpu[ppe_id][index];
++}
++EXPORT_SYMBOL(hnat_get_foe_entry);
++
+ void hnat_cache_ebl(int enable)
+ {
+ int i;
+@@ -63,6 +79,7 @@ void hnat_cache_ebl(int enable)
+ cr_set_field(hnat_priv->ppe_base[i] + PPE_CAH_CTRL, CAH_EN, enable);
+ }
+ }
++EXPORT_SYMBOL(hnat_cache_ebl);
+
+ static void hnat_reset_timestamp(struct timer_list *t)
+ {
+--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+@@ -1140,6 +1140,8 @@ enum FoeIpAct {
+ #define NR_WDMA1_PORT 9
+ #define NR_WDMA2_PORT 13
+ #define NR_GMAC3_PORT 15
++#define NR_TDMA_TPORT 4
++#define NR_TDMA_QDMA_TPORT 5
+ #define LAN_DEV_NAME hnat_priv->lan
+ #define LAN2_DEV_NAME hnat_priv->lan2
+ #define IS_WAN(dev) \
+@@ -1269,6 +1271,8 @@ static inline bool hnat_dsa_is_enable(st
+ }
+ #endif
+
++struct foe_entry *hnat_get_foe_entry(u32 ppe_id, u32 index);
++
+ void hnat_deinit_debugfs(struct mtk_hnat *h);
+ int hnat_init_debugfs(struct mtk_hnat *h);
+ int hnat_register_nf_hooks(void);
+@@ -1285,6 +1289,9 @@ extern int qos_ul_toggle;
+ extern int hook_toggle;
+ extern int mape_toggle;
+ extern int qos_toggle;
++extern int (*mtk_tnl_encap_offload)(struct sk_buff *skb);
++extern int (*mtk_tnl_decap_offload)(struct sk_buff *skb);
++extern bool (*mtk_tnl_decap_offloadable)(struct sk_buff *skb);
+
+ int ext_if_add(struct extdev_entry *ext_entry);
+ int ext_if_del(struct extdev_entry *ext_entry);
+--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+@@ -728,10 +728,14 @@ static unsigned int is_ppe_support_type(
+ case ETH_P_IP:
+ iph = ip_hdr(skb);
+
+- /* do not accelerate non tcp/udp traffic */
+- if ((iph->protocol == IPPROTO_TCP) ||
++ if (mtk_tnl_decap_offloadable && mtk_tnl_decap_offloadable(skb)) {
++ /* tunnel protocol is offloadable */
++ skb_hnat_set_is_decap(skb, 1);
++ return 1;
++ } else if ((iph->protocol == IPPROTO_TCP) ||
+ (iph->protocol == IPPROTO_UDP) ||
+ (iph->protocol == IPPROTO_IPV6)) {
++ /* do not accelerate non tcp/udp traffic */
+ return 1;
+ }
+
+@@ -848,6 +852,13 @@ mtk_hnat_ipv4_nf_pre_routing(void *priv,
+
+ hnat_set_head_frags(state, skb, -1, hnat_set_iif);
+
++ if (skb_hnat_tops(skb) && skb_hnat_is_decap(skb)
++ && is_magic_tag_valid(skb)
++ && skb_hnat_iface(skb) == FOE_MAGIC_GE_VIRTUAL
++ && mtk_tnl_decap_offload && mtk_tnl_decap_offload(skb)) {
++ return NF_ACCEPT;
++ }
++
+ /*
+ * Avoid mistakenly binding of outer IP, ports in SW L2TP decap flow.
+ * In pre-routing, if dev is virtual iface, TOPS module is not loaded,
+@@ -923,6 +934,13 @@ mtk_hnat_br_nf_local_in(void *priv, stru
+
+ hnat_set_head_frags(state, skb, -1, hnat_set_iif);
+
++ if (skb_hnat_tops(skb) && skb_hnat_is_decap(skb)
++ && is_magic_tag_valid(skb)
++ && skb_hnat_iface(skb) == FOE_MAGIC_GE_VIRTUAL
++ && mtk_tnl_decap_offload && mtk_tnl_decap_offload(skb)) {
++ return NF_ACCEPT;
++ }
++
+ pre_routing_print(skb, state->in, state->out, __func__);
+
+ if (unlikely(debug_level >= 7)) {
+@@ -1075,8 +1093,22 @@ static unsigned int hnat_ipv4_get_nextho
+ return -1;
+ }
+
++ /*
++ * if this packet is a tunnel packet and is about to construct
++ * outer header, we must update its outer mac header pointer
++ * before filling outer mac or it may screw up inner mac
++ */
++ if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) {
++ skb_push(skb, sizeof(struct ethhdr));
++ skb_reset_mac_header(skb);
++ }
++
+ memcpy(eth_hdr(skb)->h_dest, neigh->ha, ETH_ALEN);
+ memcpy(eth_hdr(skb)->h_source, out->dev_addr, ETH_ALEN);
++ eth_hdr(skb)->h_proto = htons(ETH_P_IP);
++
++ if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb))
++ skb_pull(skb, sizeof(struct ethhdr));
+
+ rcu_read_unlock_bh();
+
+@@ -1203,6 +1235,81 @@ static struct ethhdr *get_ipv6_ipip_ethh
+ return eth;
+ }
+
++static inline void hnat_get_filled_unbind_entry(struct sk_buff *skb,
++ struct foe_entry *entry)
++{
++ if (unlikely(!skb || !entry))
++ return;
++
++ memcpy(entry,
++ &hnat_priv->foe_table_cpu[skb_hnat_ppe(skb)][skb_hnat_entry(skb)],
++ sizeof(*entry));
++
++#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
++ entry->bfib1.mc = 0;
++#endif /* defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3) */
++ entry->bfib1.ka = 0;
++ entry->bfib1.vlan_layer = 0;
++ entry->bfib1.psn = 0;
++ entry->bfib1.vpm = 0;
++ entry->bfib1.ps = 0;
++}
++
++static inline void hnat_qos_tnl(u32 id, const struct net_device *dev)
++{
++ u32 cfg;
++ u32 max_man = 0;
++ u32 max_exp = 0;
++ const struct mtk_mac *mac;
++
++ if (!dev)
++ return;
++ mac = netdev_priv(dev);
++
++ switch (mac->speed) {
++ case SPEED_100:
++ case SPEED_1000:
++ case SPEED_2500:
++ case SPEED_5000:
++ case SPEED_10000:
++ max_man = mac->speed / SPEED_100;
++ max_exp = 5;
++ break;
++ default:
++ return;
++ }
++
++ cfg = QTX_SCH_MIN_RATE_EN | QTX_SCH_MAX_RATE_EN;
++ cfg |= (1 << QTX_SCH_MIN_RATE_MAN_OFFSET) |
++ (4 << QTX_SCH_MIN_RATE_EXP_OFFSET) |
++ (max_man << QTX_SCH_MAX_RATE_MAN_OFFSET) |
++ (max_exp << QTX_SCH_MAX_RATE_EXP_OFFSET) |
++ (4 << QTX_SCH_MAX_RATE_WGHT_OFFSET);
++ writel(cfg, hnat_priv->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
++}
++
++static inline void hnat_fill_offload_engine_entry(struct sk_buff *skb,
++ struct foe_entry *entry,
++ const struct net_device *dev)
++{
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++ if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb)) {
++ /*
++ * if skb_hnat_tops(skb) is setup for encapsulation,
++ * we fill in hnat tport and tops_entry for tunnel encapsulation
++ * offloading
++ */
++ entry->ipv4_hnapt.tport_id = NR_TDMA_QDMA_TPORT;
++ entry->ipv4_hnapt.tops_entry = skb_hnat_tops(skb);
++ } else {
++ return;
++ }
++
++ entry->ipv4_hnapt.iblk2.qid = 12; /* offload engine use QID 12 */
++ hnat_qos_tnl(12, dev); /* set rate limit to line rate */
++#endif /* defined(CONFIG_MEDIATEK_NETSYS_V3) */
++}
++
+ static unsigned int skb_to_hnat_info(struct sk_buff *skb,
+ const struct net_device *dev,
+ struct foe_entry *foe,
+@@ -1240,6 +1347,11 @@ static unsigned int skb_to_hnat_info(str
+ if (whnat && is_hnat_pre_filled(foe))
+ return 0;
+
++ if (skb_hnat_tops(skb) && !(hw_path->flags & FLOW_OFFLOAD_PATH_TNL)) {
++ hnat_get_filled_unbind_entry(skb, &entry);
++ goto hnat_entry_bind;
++ }
++
+ entry.bfib1.pkt_type = foe->udib1.pkt_type; /* Get packte type state*/
+ entry.bfib1.state = foe->udib1.state;
+
+@@ -1683,6 +1795,10 @@ static unsigned int skb_to_hnat_info(str
+ /* Fill Layer2 Info.*/
+ entry = ppe_fill_L2_info(eth, entry, hw_path);
+
++ if (skb_hnat_tops(skb) && hw_path->flags & FLOW_OFFLOAD_PATH_TNL)
++ goto hnat_entry_skip_bind;
++
++hnat_entry_bind:
+ /* Fill Info Blk*/
+ entry = ppe_fill_info_blk(eth, entry, hw_path);
+
+@@ -1881,7 +1997,20 @@ static unsigned int skb_to_hnat_info(str
+ entry.ipv6_5t_route.act_dp |= UDF_HNAT_PRE_FILLED;
+ }
+
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++ hnat_fill_offload_engine_entry(skb, &entry, dev);
++#endif
++
++hnat_entry_skip_bind:
+ wmb();
++
++ /*
++ * final check before we write BIND info.
++ * If this entry is already bound, we should not modify it right now
++ */
++ if (entry_hnat_is_bound(foe))
++ return 0;
++
+ memcpy(foe, &entry, sizeof(entry));
+ /*reset statistic for this entry*/
+ if (hnat_priv->data->per_flow_accounting &&
+@@ -1953,6 +2082,12 @@ int mtk_sw_nat_hook_tx(struct sk_buff *s
+ switch ((int)entry.bfib1.pkt_type) {
+ case IPV4_HNAPT:
+ case IPV4_HNAT:
++ /*
++ * skip if packet is an encap tnl packet or it may
++ * screw up inner mac header
++ */
++ if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb))
++ break;
+ entry.ipv4_hnapt.smac_hi = swab32(*((u32 *)eth->h_source));
+ entry.ipv4_hnapt.smac_lo = swab16(*((u16 *)ð->h_source[4]));
+ break;
+@@ -2144,6 +2279,10 @@ int mtk_sw_nat_hook_tx(struct sk_buff *s
+ entry.ipv6_5t_route.iblk2.dp = gmac_no;
+ }
+
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++ hnat_fill_offload_engine_entry(skb, &entry, NULL);
++#endif
++
+ entry.bfib1.ttl = 1;
+ entry.bfib1.state = BIND;
+ if (IS_IPV4_GRP(&entry))
+@@ -2219,6 +2358,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
+ }
+
+ skb_hnat_alg(skb) = 0;
++ skb_hnat_set_tops(skb, 0);
+ skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
+
+ if (skb_hnat_iface(skb) == FOE_MAGIC_WED0)
+@@ -2672,6 +2812,7 @@ static unsigned int mtk_hnat_nf_post_rou
+ struct flow_offload_hw_path hw_path = { .dev = (struct net_device*)out,
+ .virt_dev = (struct net_device*)out };
+ const struct net_device *arp_dev = out;
++ bool is_virt_dev = false;
+
+ if (xlat_toggle && !mtk_464xlat_post_process(skb, out))
+ return 0;
+@@ -2691,10 +2832,29 @@ static unsigned int mtk_hnat_nf_post_rou
+
+ if (out->netdev_ops->ndo_flow_offload_check) {
+ out->netdev_ops->ndo_flow_offload_check(&hw_path);
++
+ out = (IS_GMAC1_MODE) ? hw_path.virt_dev : hw_path.dev;
++ if (hw_path.flags & FLOW_OFFLOAD_PATH_TNL && mtk_tnl_encap_offload) {
++ if (ntohs(skb->protocol) == ETH_P_IP
++ && ip_hdr(skb)->protocol == IPPROTO_TCP) {
++ skb_hnat_set_tops(skb, hw_path.tnl_type + 1);
++ } else {
++ /*
++ * we are not support protocols other than IPv4 TCP
++ * for tunnel protocol offload yet
++ */
++ skb_hnat_alg(skb) = 1;
++ return 0;
++ }
++ }
+ }
+
+ if (!IS_LAN_GRP(out) && !IS_WAN(out) && !IS_EXT(out))
++ is_virt_dev = true;
++
++ if (is_virt_dev
++ && !(skb_hnat_tops(skb) && skb_hnat_is_encap(skb)
++ && (hw_path.flags & FLOW_OFFLOAD_PATH_TNL)))
+ return 0;
+
+ trace_printk("[%s] case hit, %x-->%s, reason=%x\n", __func__,
+@@ -2714,9 +2874,18 @@ static unsigned int mtk_hnat_nf_post_rou
+ if (fn && !mtk_hnat_accel_type(skb))
+ break;
+
+- if (fn && fn(skb, arp_dev, &hw_path))
++ if (!is_virt_dev && fn && fn(skb, arp_dev, &hw_path))
+ break;
+
++ /* skb_hnat_tops(skb) is updated in mtk_tnl_offload() */
++ if (skb_hnat_tops(skb)) {
++ if (skb_hnat_is_encap(skb) && !is_virt_dev
++ && mtk_tnl_encap_offload && mtk_tnl_encap_offload(skb))
++ break;
++ if (skb_hnat_is_decap(skb))
++ break;
++ }
++
+ spin_lock(&hnat_priv->entry_lock);
+ skb_to_hnat_info(skb, out, entry, &hw_path);
+ spin_unlock(&hnat_priv->entry_lock);
+@@ -2989,7 +3158,7 @@ mtk_hnat_ipv4_nf_local_out(void *priv, s
+ if (iph->protocol == IPPROTO_IPV6) {
+ entry->udib1.pkt_type = IPV6_6RD;
+ hnat_set_head_frags(state, skb, 0, hnat_set_alg);
+- } else {
++ } else if (!skb_hnat_tops(skb)) {
+ hnat_set_head_frags(state, skb, 1, hnat_set_alg);
+ }
+
+--- a/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
+@@ -44,7 +44,9 @@ struct hnat_desc {
+ u32 is_sp : 1;
+ u32 hf : 1;
+ u32 amsdu : 1;
+- u32 resv3 : 19;
++ u32 tops : 6;
++ u32 is_decap : 1;
++ u32 resv3 : 12;
+ u32 magic_tag_protect : 16;
+ } __packed;
+ #elif defined(CONFIG_MEDIATEK_NETSYS_RX_V2)
+@@ -91,6 +93,19 @@ struct hnat_desc {
+ ((((skb_headroom(skb) >= FOE_INFO_LEN) ? 1 : 0)))
+
+ #define skb_hnat_info(skb) ((struct hnat_desc *)(skb->head))
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++#define skb_hnat_tops(skb) (((struct hnat_desc *)((skb)->head))->tops)
++#define skb_hnat_is_decap(skb) (((struct hnat_desc *)((skb)->head))->is_decap)
++#define skb_hnat_is_encap(skb) (!skb_hnat_is_decap(skb))
++#define skb_hnat_set_tops(skb, tops) ((skb_hnat_tops(skb)) = (tops))
++#define skb_hnat_set_is_decap(skb, is_decap) ((skb_hnat_is_decap(skb)) = (is_decap))
++#else /* !defined(CONFIG_MEDIATEK_NETSYS_V3) */
++#define skb_hnat_tops(skb) (0)
++#define skb_hnat_is_decap(skb) (0)
++#define skb_hnat_is_encap(skb) (0)
++#define skb_hnat_set_tops(skb, tops)
++#define skb_hnat_set_is_decap(skb, is_decap)
++#endif /* defined(CONFIG_MEDIATEK_NETSYS_V3) */
+ #define skb_hnat_magic(skb) (((struct hnat_desc *)(skb->head))->magic)
+ #define skb_hnat_reason(skb) (((struct hnat_desc *)(skb->head))->crsn)
+ #define skb_hnat_entry(skb) (((struct hnat_desc *)(skb->head))->entry)
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -98,10 +98,21 @@ struct flow_offload {
+ #define FLOW_OFFLOAD_PATH_6RD BIT(5)
+ #define FLOW_OFFLOAD_PATH_TNL BIT(6)
+
++enum flow_offload_tnl {
++ FLOW_OFFLOAD_TNL_GRETAP,
++ FLOW_OFFLOAD_TNL_PPTP,
++ FLOW_OFFLOAD_TNL_L2TP_V2,
++ FLOW_OFFLOAD_TNL_L2TP_V3,
++ FLOW_OFFLOAD_VXLAN,
++ FLOW_OFFLOAD_NATT,
++ __FLOW_OFFLOAD_MAX,
++};
++
+ struct flow_offload_hw_path {
+ struct net_device *dev;
+ struct net_device *virt_dev;
+ u32 flags;
++ u32 tnl_type;
+
+ u8 eth_src[ETH_ALEN];
+ u8 eth_dest[ETH_ALEN];
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4101-mtk-tunnel-network-service-error-recover-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4101-mtk-tunnel-network-service-error-recover-support.patch
index 9f9e26a..a2579c0 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4101-mtk-tunnel-network-service-error-recover-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4101-mtk-tunnel-network-service-error-recover-support.patch
@@ -38,7 +38,7 @@
#define MTK_ETHTOOL_STAT(x) { #x, \
offsetof(struct mtk_hw_stats, x) / sizeof(u64) }
-@@ -4141,6 +4142,8 @@ static void mtk_pending_work(struct work
+@@ -4178,6 +4179,8 @@ static void mtk_pending_work(struct work
}
pr_warn("wait for MTK_FE_START_RESET\n");
}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4102-mtk-crypto-offload-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4102-mtk-crypto-offload-support.patch
index 96deb54..455ff04 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4102-mtk-crypto-offload-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4102-mtk-crypto-offload-support.patch
@@ -1,21 +1,24 @@
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -1840,6 +1840,11 @@ static void mtk_tx_set_dma_desc_v3(struc
+@@ -1857,6 +1857,12 @@ static void mtk_tx_set_dma_desc_v3(struc
+
trace_printk("[%s] skb_shinfo(skb)->nr_frags=%x HNAT_SKB_CB2(skb)->magic=%x txd4=%x<-----\n",
__func__, skb_shinfo(skb)->nr_frags, HNAT_SKB_CB2(skb)->magic, data);
- #endif
++
+ /* forward to eip197 if this packet is going to encrypt */
+ if (unlikely(skb_hnat_cdrt(skb) && is_magic_tag_valid(skb))) {
+ data &= ((~TX_DMA_TPORT_MASK) << TX_DMA_TPORT_SHIFT);
+ data |= (EIP197_QDMA_TPORT & TX_DMA_TPORT_MASK) << TX_DMA_TPORT_SHIFT;
+ }
+ #endif
WRITE_ONCE(desc->txd4, data);
- data = 0;
-@@ -1862,6 +1867,14 @@ static void mtk_tx_set_dma_desc_v3(struc
+@@ -1880,6 +1886,17 @@ static void mtk_tx_set_dma_desc_v3(struc
WRITE_ONCE(desc->txd7, 0);
WRITE_ONCE(desc->txd8, 0);
++
++#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
+ if (unlikely(skb_hnat_cdrt(skb) && is_magic_tag_valid(skb))) {
+ /* carry cdrt index for encryption */
+ data = (skb_hnat_cdrt(skb) & TX_DMA_CDRT_MASK) << TX_DMA_CDRT_SHIFT;
@@ -24,10 +27,11 @@
+ } else {
+ WRITE_ONCE(desc->txd8, 0);
+ }
++#endif
}
static void mtk_tx_set_dma_desc(struct sk_buff *skb, struct net_device *dev, void *txd,
-@@ -2331,6 +2344,7 @@ static int mtk_poll_rx(struct napi_struc
+@@ -2307,6 +2324,7 @@ static int mtk_poll_rx(struct napi_struc
skb_hnat_alg(skb) = 0;
skb_hnat_filled(skb) = 0;
@@ -37,7 +41,7 @@
skb_hnat_set_is_decap(skb, 0);
--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
-@@ -1076,6 +1076,9 @@ static unsigned int hnat_ipv4_get_nextho
+@@ -1078,6 +1078,9 @@ static unsigned int hnat_ipv4_get_nextho
return 0;
}
@@ -47,7 +51,7 @@
rcu_read_lock_bh();
nexthop = (__force u32)rt_nexthop(rt, ip_hdr(skb)->daddr);
neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
-@@ -1299,6 +1302,9 @@ static inline void hnat_fill_offload_eng
+@@ -1302,6 +1305,9 @@ static inline void hnat_fill_offload_eng
*/
entry->ipv4_hnapt.tport_id = NR_TDMA_QDMA_TPORT;
entry->ipv4_hnapt.tops_entry = skb_hnat_tops(skb);
@@ -57,7 +61,7 @@
} else {
return;
}
-@@ -1308,6 +1314,75 @@ static inline void hnat_fill_offload_eng
+@@ -1311,6 +1317,79 @@ static inline void hnat_fill_offload_eng
#endif /* defined(CONFIG_MEDIATEK_NETSYS_V3) */
}
@@ -66,6 +70,7 @@
+ struct foe_entry entry = { 0 };
+ struct ethhdr *eth = eth_hdr(skb);
+ u32 gmac = NR_DISCARD;
++ struct mtk_mac *mac = netdev_priv(dev);
+
+ if (skb_hnat_tops(skb) && mtk_tnl_encap_offload)
+ mtk_tnl_encap_offload(skb);
@@ -89,9 +94,12 @@
+ else
+ gmac = NR_GMAC1_PORT;
+ } else if (IS_LAN2(dev)) {
-+ gmac = NR_GMAC2_PORT;
++ gmac = (mac->id == MTK_GMAC2_ID) ? NR_GMAC2_PORT : NR_GMAC3_PORT;
+ } else if (IS_WAN(dev)) {
-+ gmac = (IS_GMAC1_MODE) ? NR_GMAC1_PORT : NR_GMAC2_PORT;
++ if (IS_GMAC1_MODE)
++ gmac = NR_GMAC1_PORT;
++ else
++ gmac = (mac->id == MTK_GMAC2_ID) ? NR_GMAC2_PORT : NR_GMAC3_PORT;
+ } else {
+ pr_notice("Unknown case of dp, iif=%x --> %s\n", skb_hnat_iface(skb), dev->name);
+ return -1;
@@ -133,7 +141,7 @@
static unsigned int skb_to_hnat_info(struct sk_buff *skb,
const struct net_device *dev,
struct foe_entry *foe,
-@@ -2364,6 +2439,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
+@@ -2360,6 +2439,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
skb_hnat_alg(skb) = 0;
skb_hnat_set_tops(skb, 0);
@@ -141,7 +149,7 @@
skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
if (skb_hnat_iface(skb) == FOE_MAGIC_WED0)
-@@ -2450,7 +2526,8 @@ static unsigned int mtk_hnat_accel_type(
+@@ -2446,7 +2526,8 @@ static unsigned int mtk_hnat_accel_type(
* is from local_out which is also filtered in sanity check.
*/
dst = skb_dst(skb);
@@ -151,7 +159,7 @@
return 0;
ct = nf_ct_get(skb, &ctinfo);
-@@ -2847,6 +2924,14 @@ static unsigned int mtk_hnat_nf_post_rou
+@@ -2850,6 +2931,14 @@ static unsigned int mtk_hnat_nf_post_rou
}
}
@@ -166,7 +174,7 @@
if (!IS_LAN_GRP(out) && !IS_WAN(out) && !IS_EXT(out))
is_virt_dev = true;
-@@ -3157,7 +3242,10 @@ mtk_hnat_ipv4_nf_local_out(void *priv, s
+@@ -3159,7 +3248,10 @@ mtk_hnat_ipv4_nf_local_out(void *priv, s
if (iph->protocol == IPPROTO_IPV6) {
entry->udib1.pkt_type = IPV6_6RD;
hnat_set_head_frags(state, skb, 0, hnat_set_alg);
@@ -220,7 +228,7 @@
{
--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
-@@ -1135,6 +1135,8 @@ enum FoeIpAct {
+@@ -1140,6 +1140,8 @@ enum FoeIpAct {
#define NR_WDMA1_PORT 9
#define NR_WDMA2_PORT 13
#define NR_GMAC3_PORT 15
@@ -229,7 +237,7 @@
#define NR_TDMA_TPORT 4
#define NR_TDMA_QDMA_TPORT 5
#define LAN_DEV_NAME hnat_priv->lan
-@@ -1288,6 +1290,8 @@ extern int qos_toggle;
+@@ -1292,6 +1294,8 @@ extern int qos_toggle;
extern int (*mtk_tnl_encap_offload)(struct sk_buff *skb);
extern int (*mtk_tnl_decap_offload)(struct sk_buff *skb);
extern bool (*mtk_tnl_decap_offloadable)(struct sk_buff *skb);
@@ -240,7 +248,7 @@
int ext_if_del(struct extdev_entry *ext_entry);
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -551,6 +551,10 @@
+@@ -558,6 +558,10 @@
#define MTK_QDMA_GMAC2_QID 8
@@ -251,7 +259,7 @@
/* QDMA V2 descriptor txd6 */
#define TX_DMA_INS_VLAN_V2 BIT(16)
-@@ -560,6 +564,9 @@
+@@ -567,6 +571,9 @@
#define TX_DMA_SPTAG_V3 BIT(27)
/* QDMA V2 descriptor txd4 */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4103-mtk-tunnel-crypto-offload-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4103-mtk-tunnel-crypto-offload-support.patch
index 608bc91..b96f080 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4103-mtk-tunnel-crypto-offload-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4103-mtk-tunnel-crypto-offload-support.patch
@@ -1,6 +1,6 @@
--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
-@@ -1139,6 +1139,8 @@ enum FoeIpAct {
+@@ -1144,6 +1144,8 @@ enum FoeIpAct {
#define NR_EIP197_QDMA_TPORT 3
#define NR_TDMA_TPORT 4
#define NR_TDMA_QDMA_TPORT 5
@@ -21,9 +21,9 @@
skb_push(skb, sizeof(struct ethhdr));
skb_reset_mac_header(skb);
}
-@@ -1109,7 +1110,8 @@ static unsigned int hnat_ipv4_get_nextho
- memcpy(eth_hdr(skb)->h_dest, neigh->ha, ETH_ALEN);
+@@ -1110,7 +1111,8 @@ static unsigned int hnat_ipv4_get_nextho
memcpy(eth_hdr(skb)->h_source, out->dev_addr, ETH_ALEN);
+ eth_hdr(skb)->h_proto = htons(ETH_P_IP);
- if (skb_hnat_tops(skb) && skb_hnat_is_encap(skb))
+ if ((skb_hnat_tops(skb) && skb_hnat_is_encap(skb))
@@ -31,7 +31,7 @@
skb_pull(skb, sizeof(struct ethhdr));
rcu_read_unlock_bh();
-@@ -1257,6 +1259,38 @@ static inline void hnat_get_filled_unbin
+@@ -1258,6 +1260,38 @@ static inline void hnat_get_filled_unbin
entry->bfib1.ps = 0;
}
@@ -70,7 +70,7 @@
static inline void hnat_qos_tnl(u32 id, const struct net_device *dev)
{
u32 cfg;
-@@ -1301,9 +1335,15 @@ static inline void hnat_fill_offload_eng
+@@ -1302,9 +1336,15 @@ static inline void hnat_fill_offload_eng
* we fill in hnat tport and tops_entry for tunnel encapsulation
* offloading
*/
@@ -88,7 +88,7 @@
entry->ipv4_hnapt.tport_id = NR_EIP197_QDMA_TPORT;
entry->ipv4_hnapt.cdrt_id = skb_hnat_cdrt(skb);
} else {
-@@ -1404,6 +1444,7 @@ static unsigned int skb_to_hnat_info(str
+@@ -1405,6 +1445,7 @@ static unsigned int skb_to_hnat_info(str
u32 port_id = 0;
u32 payload_len = 0;
int mape = 0;
@@ -96,7 +96,7 @@
struct mtk_mac *mac = netdev_priv(dev);
ct = nf_ct_get(skb, &ctinfo);
-@@ -1421,9 +1462,12 @@ static unsigned int skb_to_hnat_info(str
+@@ -1422,9 +1463,12 @@ static unsigned int skb_to_hnat_info(str
if (whnat && is_hnat_pre_filled(foe))
return 0;
@@ -110,7 +110,7 @@
}
entry.bfib1.pkt_type = foe->udib1.pkt_type; /* Get packte type state*/
-@@ -1869,7 +1913,9 @@ static unsigned int skb_to_hnat_info(str
+@@ -1870,7 +1914,9 @@ static unsigned int skb_to_hnat_info(str
/* Fill Layer2 Info.*/
entry = ppe_fill_L2_info(eth, entry, hw_path);
@@ -121,7 +121,7 @@
goto hnat_entry_skip_bind;
hnat_entry_bind:
-@@ -2445,6 +2491,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
+@@ -2435,6 +2481,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
skb_hnat_alg(skb) = 0;
skb_hnat_set_tops(skb, 0);
skb_hnat_set_cdrt(skb, 0);
@@ -129,7 +129,7 @@
skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
if (skb_hnat_iface(skb) == FOE_MAGIC_WED0)
-@@ -3248,7 +3295,8 @@ mtk_hnat_ipv4_nf_local_out(void *priv, s
+@@ -3244,7 +3291,8 @@ mtk_hnat_ipv4_nf_local_out(void *priv, s
entry->udib1.pkt_type = IPV6_6RD;
hnat_set_head_frags(state, skb, 0, hnat_set_alg);
} else if (is_magic_tag_valid(skb)
@@ -141,7 +141,7 @@
hnat_set_head_frags(state, skb, 1, hnat_set_alg);
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2306,10 +2306,11 @@ static int mtk_poll_rx(struct napi_struc
+@@ -2324,10 +2324,11 @@ static int mtk_poll_rx(struct napi_struc
skb_hnat_alg(skb) = 0;
skb_hnat_filled(skb) = 0;
@@ -156,7 +156,7 @@
trace_printk("[%s] reason=0x%x(force to CPU) from WAN to Ext\n",
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -652,6 +652,9 @@
+@@ -656,6 +656,9 @@
#define RX_DMA_GET_AGG_CNT_V2(_x) (((_x) >> 16) & 0xff)
#define RX_DMA_GET_TOPS_CRSN(_x) (((_x) >> 24) & 0xff)
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4500-mtk-ppp-offload-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4500-mtk-ppp-offload-support.patch
new file mode 100644
index 0000000..1409f9f
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4500-mtk-ppp-offload-support.patch
@@ -0,0 +1,65 @@
+--- a/drivers/net/ppp/ppp_generic.c
++++ b/drivers/net/ppp/ppp_generic.c
+@@ -296,6 +296,9 @@ static void unit_put(struct idr *p, int
+ static void *unit_find(struct idr *p, int n);
+ static void ppp_setup(struct net_device *dev);
+
++struct sock *ppp_netdev_get_sock(struct net_device *dev);
++EXPORT_SYMBOL(ppp_netdev_get_sock);
++
+ static const struct net_device_ops ppp_netdev_ops;
+
+ static struct class *ppp_class;
+@@ -1660,6 +1663,40 @@ ppp_send_frame(struct ppp *ppp, struct s
+ ++ppp->dev->stats.tx_errors;
+ }
+
++struct sock *ppp_netdev_get_sock(struct net_device *dev)
++{
++ struct list_head *list;
++ struct channel *pch;
++ struct ppp *ppp;
++ struct sock *sk;
++
++ if (!dev)
++ return ERR_PTR(-EINVAL);
++
++ ppp = netdev_priv(dev);
++
++ list = &ppp->channels;
++ if (list_empty(list))
++ /* nowhere to send the packet */
++ return ERR_PTR(-EINVAL);
++
++ if (ppp->flags & SC_MULTILINK)
++ /* not doing multilink: send it down the first channel */
++ return ERR_PTR(-EPERM);
++
++ list = list->next;
++ pch = list_entry(list, struct channel, clist);
++
++ spin_lock(&pch->downl);
++ if (pch->chan)
++ sk = (struct sock *)pch->chan->private;
++ else
++ sk = ERR_PTR(-EINVAL);
++ spin_unlock(&pch->downl);
++
++ return sk;
++}
++
+ /*
+ * Try to send the frame in xmit_pending.
+ * The caller should have the xmit path locked.
+--- a/include/linux/ppp_channel.h
++++ b/include/linux/ppp_channel.h
+@@ -75,6 +75,9 @@ extern int ppp_unit_number(struct ppp_ch
+ /* Get the device name associated with a channel, or NULL if none */
+ extern char *ppp_dev_name(struct ppp_channel *);
+
++/* Get the socket structure of a given ppp netdev */
++extern struct sock *ppp_netdev_get_sock(struct net_device *dev);
++
+ /*
+ * SMP locking notes:
+ * The channel code must ensure that when it calls ppp_unregister_channel,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4500-mtk-l2tp-offload-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4501-mtk-l2tp-offload-support.patch
similarity index 90%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4500-mtk-l2tp-offload-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4501-mtk-l2tp-offload-support.patch
index e6583b6..5e16ba8 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4500-mtk-l2tp-offload-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4501-mtk-l2tp-offload-support.patch
@@ -13,7 +13,7 @@
* make room. Adjust truesize.
--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
-@@ -855,7 +855,8 @@ mtk_hnat_ipv4_nf_pre_routing(void *priv,
+@@ -865,7 +865,8 @@ mtk_hnat_ipv4_nf_pre_routing(void *priv,
* and it's L2TP flow, then do not bind.
*/
if (skb_hnat_iface(skb) == FOE_MAGIC_GE_VIRTUAL
@@ -29,7 +29,7 @@
return -EINVAL;
path->flags |= FLOW_OFFLOAD_PATH_TNL;
-+ path->tnl_type = FLOW_OFFLOAD_TNL_UDP_L2TP_DATA;
++ path->tnl_type = FLOW_OFFLOAD_TNL_L2TP_V2;
return 0;
}
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4501-mtk-pptp-offload-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4501-mtk-pptp-offload-support.patch
new file mode 100644
index 0000000..ec218e1
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/nf_hnat/999-4501-mtk-pptp-offload-support.patch
@@ -0,0 +1,100 @@
+--- a/drivers/net/ppp/pptp.c
++++ b/drivers/net/ppp/pptp.c
+@@ -33,6 +33,7 @@
+ #include <net/route.h>
+ #include <net/gre.h>
+ #include <net/pptp.h>
++#include <net/netfilter/nf_flow_table.h>
+
+ #include <linux/uaccess.h>
+
+@@ -40,6 +41,9 @@
+
+ #define MAX_CALLID 65535
+
++int (*mtk_pptp_seq_next)(u16 call_id, u32 *val) = NULL;
++EXPORT_SYMBOL(mtk_pptp_seq_next);
++
+ static DECLARE_BITMAP(callid_bitmap, MAX_CALLID + 1);
+ static struct pppox_sock __rcu **callid_sock;
+
+@@ -128,6 +132,26 @@ static void del_chan(struct pppox_sock *
+ spin_unlock(&chan_lock);
+ }
+
++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
++static int pptp_flow_offload_check(struct ppp_channel *chan,
++ struct flow_offload_hw_path *path)
++{
++ struct sock *sk = (struct sock *)chan->private;
++ struct pppox_sock *po = pppox_sk(sk);
++
++ if (path->flags & FLOW_OFFLOAD_PATH_TNL)
++ return -EEXIST;
++
++ if (sk_pppox(po)->sk_state & PPPOX_DEAD)
++ return -EINVAL;
++
++ path->flags |= FLOW_OFFLOAD_PATH_TNL;
++ path->tnl_type = FLOW_OFFLOAD_TNL_PPTP;
++
++ return 0;
++}
++#endif /* IS_ENABLED(CONFIG_NF_FLOW_TABLE) */
++
+ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+ {
+ struct sock *sk = (struct sock *) chan->private;
+@@ -140,6 +164,7 @@ static int pptp_xmit(struct ppp_channel
+ int islcp;
+ int len;
+ unsigned char *data;
++ u32 seq_sent_hw;
+ __u32 seq_recv;
+
+
+@@ -204,7 +229,14 @@ static int pptp_xmit(struct ppp_channel
+ hdr->gre_hd.protocol = GRE_PROTO_PPP;
+ hdr->call_id = htons(opt->dst_addr.call_id);
+
+- hdr->seq = htonl(++opt->seq_sent);
++ if (mtk_pptp_seq_next && !mtk_pptp_seq_next(opt->dst_addr.call_id,
++ &seq_sent_hw)) {
++ opt->seq_sent = seq_sent_hw;
++ hdr->seq = htonl(opt->seq_sent);
++ } else {
++ hdr->seq = htonl(++opt->seq_sent);
++ }
++
+ if (opt->ack_sent != seq_recv) {
+ /* send ack with this message */
+ hdr->gre_hd.flags |= GRE_ACK;
+@@ -598,6 +630,9 @@ static int pptp_ppp_ioctl(struct ppp_cha
+ static const struct ppp_channel_ops pptp_chan_ops = {
+ .start_xmit = pptp_xmit,
+ .ioctl = pptp_ppp_ioctl,
++#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
++ .flow_offload_check = pptp_flow_offload_check,
++#endif /* IS_ENABLED(CONFIG_NF_FLOW_TABLE) */
+ };
+
+ static struct proto pptp_sk_proto __read_mostly = {
+--- a/include/net/pptp.h
++++ b/include/net/pptp.h
+@@ -2,6 +2,8 @@
+ #ifndef _NET_PPTP_H
+ #define _NET_PPTP_H
+
++#include <net/gre.h>
++
+ #define PPP_LCP_ECHOREQ 0x09
+ #define PPP_LCP_ECHOREP 0x0A
+ #define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
+@@ -20,5 +22,7 @@ struct pptp_gre_header {
+ __be32 ack;
+ } __packed;
+
++/* symbol exported from linux kernel driver/net/ppp/pptp.c */
++extern int (*mtk_pptp_seq_next)(uint16_t call_id, uint32_t *val);
+
+ #endif
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1050-v6.4-backport-jitterrng-2.2.0.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1050-v6.4-backport-jitterrng-2.2.0.patch
new file mode 100644
index 0000000..3e85026
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1050-v6.4-backport-jitterrng-2.2.0.patch
@@ -0,0 +1,1158 @@
+diff --git a/crypto/Makefile b/crypto/Makefile
+index 4e7a0a8f7..2b5a2a9c8 100644
+--- a/crypto/Makefile
++++ b/crypto/Makefile
+@@ -156,6 +156,7 @@ CFLAGS_jitterentropy.o = -O0
+ KASAN_SANITIZE_jitterentropy.o = n
+ UBSAN_SANITIZE_jitterentropy.o = n
+ jitterentropy_rng-y := jitterentropy.o jitterentropy-kcapi.o
++jitterentropy_rng-$(CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG) += jitterentropy-dbg.o
+ obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
+ obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o
+ obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o
+diff --git a/crypto/jitterentropy-dbg.c b/crypto/jitterentropy-dbg.c
+new file mode 100644
+index 000000000..2e7e98b9a
+--- /dev/null
++++ b/crypto/jitterentropy-dbg.c
+@@ -0,0 +1,242 @@
++/*
++ * Non-physical true random number generator based on timing jitter - DebugFS
++ *
++ * Copyright Stephan Mueller <smueller@chronox.de>, 2013
++ *
++ * License
++ * =======
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, and the entire permission notice in its entirety,
++ * including the disclaimer of warranties.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * ALTERNATIVELY, this product may be distributed under the terms of
++ * the GNU General Public License, in which case the provisions of the GPL are
++ * required INSTEAD OF the above restrictions. (This clause is
++ * necessary due to a potential bad interaction between the GPL and
++ * the restrictions contained in a BSD-style copyright.)
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
++ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
++ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
++ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
++ * DAMAGE.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <asm/uaccess.h>
++#include <linux/string.h>
++#include <linux/compat.h>
++#include <linux/export.h>
++#include <linux/file.h>
++#include <linux/debugfs.h>
++
++#include "jitterentropy.h"
++#include "jitterentropy-dbg.h"
++
++struct jent_debugfs {
++ struct dentry *jent_debugfs_root;
++ struct dentry *jent_debugfs_entropy;
++ struct dentry *jent_debugfs_noise;
++};
++
++struct jent_raw
++{
++ spinlock_t raw_lock;
++ struct rand_data *entropy_collector;
++};
++
++static struct jent_debugfs jent_debugfs;
++static struct jent_raw raw_entropy;
++
++void jent_drng_cleanup_raw(struct jent_raw *raw)
++{
++ spin_lock_bh(&raw->raw_lock);
++ if (NULL != raw->entropy_collector)
++ jent_entropy_collector_free(raw->entropy_collector);
++ raw->entropy_collector = NULL;
++ spin_unlock_bh(&raw->raw_lock);
++}
++
++int jent_drng_get_bytes_raw(struct jent_raw *raw, char *data, size_t len)
++{
++ int ret = 0;
++
++ spin_lock_bh(&raw->raw_lock);
++ ret = jent_read_entropy(raw->entropy_collector, data, len);
++ if (0 > ret) {
++ printk(DRIVER_NAME": Unable to obtain %zu bytes of entropy\n", len);
++ ret = -EAGAIN;
++ }
++
++ spin_unlock_bh(&raw->raw_lock);
++ return ret;
++}
++
++
++static inline int jent_dbg_raw_bytes(char *data, size_t len)
++{
++ return jent_drng_get_bytes_raw(&raw_entropy, data, len);
++}
++
++static ssize_t jent_debugfs_read_func(struct file *file,
++ char __user *buf, size_t nbytes,
++ loff_t *ppos, size_t chunk,
++ int (*source)(char *out, size_t len))
++{
++ ssize_t total = 0;
++ int ret = 0;
++ loff_t pos = *ppos;
++ char *out;
++
++ if (!nbytes)
++ return -EINVAL;
++
++ out = kzalloc(chunk, GFP_KERNEL);
++ if (!out)
++ return -ENOMEM;
++
++ while (nbytes > 0) {
++ int copy = min_t(int, chunk, nbytes);
++ ret = source(out, copy);
++ if (0 > ret) {
++ printk(DRIVER_NAME": could not obtain random data: %d\n", ret);
++ ret = -EAGAIN;
++ break;
++ }
++ if (copy_to_user(buf+pos+total, out, ret)) {
++ ret = -EFAULT;
++ break;
++ }
++ nbytes -= ret;
++ total += ret;
++ }
++ kzfree(out);
++
++ return ((0 > ret) ? ret : total);
++}
++
++static ssize_t jent_debugfs_noise_read(struct file *file, char __user *buf,
++ size_t nbytes, loff_t *ppos)
++{
++ struct rand_data *ec = raw_entropy.entropy_collector;
++ int total = 0;
++ loff_t pos = *ppos;
++ char *out;
++
++ out = kzalloc(8, GFP_KERNEL);
++
++ while (nbytes > 0) {
++ int len = min_t(int, 8, nbytes);
++ jent_lfsr_time(ec, 0, 0, 0);
++ memcpy(out, &ec->data, len);
++ if (copy_to_user(buf+pos+total, out, len)) {
++ break;
++ }
++ nbytes -= len;
++ total += len;
++ }
++ kzfree(out);
++ return total;
++
++}
++static ssize_t jent_debugfs_seed_read(struct file *file, char __user *buf,
++ size_t nbytes, loff_t *ppos)
++{
++ int ret = jent_debugfs_read_func(file, buf, nbytes, ppos, 8,
++ jent_dbg_raw_bytes);
++ return ret;
++}
++
++int jent_drng_init_raw(struct jent_raw *raw, unsigned int flags)
++{
++ int ret = 0;
++
++ raw->entropy_collector = jent_entropy_collector_alloc(1, flags);
++ if (!raw->entropy_collector)
++ ret = -ENOMEM;
++
++ spin_lock_init(&raw->raw_lock);
++ return ret;
++}
++
++static struct file_operations jent_seed_fops = {
++ .owner = THIS_MODULE,
++ .read = jent_debugfs_seed_read,
++};
++
++static struct file_operations jent_noise_fops = {
++ .owner = THIS_MODULE,
++ .read = jent_debugfs_noise_read,
++};
++
++
++int __init jent_dbg_init(void)
++{
++ int ret = -EINVAL;
++ jent_debugfs.jent_debugfs_root = NULL;
++ jent_debugfs.jent_debugfs_noise = NULL;
++ jent_debugfs.jent_debugfs_entropy = NULL;
++
++ ret = jent_drng_init_raw(&raw_entropy, JENT_DISABLE_STIR);
++ if (ret) {
++ printk(DRIVER_NAME": Raw entropy collector instantiation failed\n");
++ return ret;
++ }
++ jent_debugfs.jent_debugfs_root =
++ debugfs_create_dir(DRIVER_NAME, NULL);
++ if (IS_ERR(jent_debugfs.jent_debugfs_root)) {
++ printk(DRIVER_NAME": initialization of debugfs directory failed\n");
++ goto cleandir;
++ }
++
++ jent_debugfs.jent_debugfs_entropy =
++ debugfs_create_file("entropy", S_IRUGO,
++ jent_debugfs.jent_debugfs_root,
++ NULL, &jent_seed_fops);
++ if (IS_ERR(jent_debugfs.jent_debugfs_entropy)) {
++ printk(DRIVER_NAME": initialization of entropy file failed\n");
++ goto cleandir;
++ }
++
++ jent_debugfs.jent_debugfs_noise =
++ debugfs_create_file("noise", S_IRUGO,
++ jent_debugfs.jent_debugfs_root,
++ NULL, &jent_noise_fops);
++ if (IS_ERR(jent_debugfs.jent_debugfs_noise)) {
++ printk(DRIVER_NAME": initialization of noise file failed\n");
++ goto cleandir;
++ }
++ return 0;
++
++cleandir:
++ debugfs_remove_recursive(jent_debugfs.jent_debugfs_root);
++ jent_drng_cleanup_raw(&raw_entropy);
++
++ return ret;
++}
++
++void jent_dbg_exit(void)
++{
++ debugfs_remove_recursive(jent_debugfs.jent_debugfs_root);
++ jent_drng_cleanup_raw(&raw_entropy);
++}
+diff --git a/crypto/jitterentropy-dbg.h b/crypto/jitterentropy-dbg.h
+new file mode 100644
+index 000000000..921bd65dc
+--- /dev/null
++++ b/crypto/jitterentropy-dbg.h
+@@ -0,0 +1,49 @@
++/*
++ * Non-physical true random number generator based on timing jitter.
++ *
++ * Copyright Stephan Mueller <smueller@chronox.de>, 2013
++ *
++ * License
++ * =======
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, and the entire permission notice in its entirety,
++ * including the disclaimer of warranties.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 3. The name of the author may not be used to endorse or promote
++ * products derived from this software without specific prior
++ * written permission.
++ *
++ * ALTERNATIVELY, this product may be distributed under the terms of
++ * the GNU General Public License, in which case the provisions of the GPL are
++ * required INSTEAD OF the above restrictions. (This clause is
++ * necessary due to a potential bad interaction between the GPL and
++ * the restrictions contained in a BSD-style copyright.)
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
++ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
++ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
++ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
++ * DAMAGE.
++ */
++
++#ifndef _JITTERENTROPY_DBG_KERNEL_H
++#define _JITTERENTROPY_DBG_KERNEL_H
++
++int __init jent_dbg_init(void);
++void jent_dbg_exit(void);
++
++
++#endif /* _JITTERENTROPY_DBG_KERNEL_H */
+diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c
+index 701b8d86a..7a3691fab 100644
+--- a/crypto/jitterentropy-kcapi.c
++++ b/crypto/jitterentropy-kcapi.c
+@@ -44,13 +44,11 @@
+ #include <linux/crypto.h>
+ #include <crypto/internal/rng.h>
+
+-struct rand_data;
+-int jent_read_entropy(struct rand_data *ec, unsigned char *data,
+- unsigned int len);
+-int jent_entropy_init(void);
+-struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
+- unsigned int flags);
+-void jent_entropy_collector_free(struct rand_data *entropy_collector);
++#include "jitterentropy.h"
++
++#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG
++#include "jitterentropy-dbg.h"
++#endif
+
+ /***************************************************************************
+ * Helper function
+@@ -148,7 +146,31 @@ static int jent_kcapi_random(struct crypto_rng *tfm,
+ int ret = 0;
+
+ spin_lock(&rng->jent_lock);
++
+ ret = jent_read_entropy(rng->entropy_collector, rdata, dlen);
++
++ if (ret == -3) {
++ /* Handle permanent health test error */
++ /*
++ * If the kernel was booted with fips=1, it implies that
++ * the entire kernel acts as a FIPS 140 module. In this case
++ * an SP800-90B permanent health test error is treated as
++ * a FIPS module error.
++ */
++ if (fips_enabled)
++ panic("Jitter RNG permanent health test failure\n");
++
++ pr_err("Jitter RNG permanent health test failure\n");
++ ret = -EFAULT;
++ } else if (ret == -2) {
++ /* Handle intermittent health test error */
++ pr_warn_ratelimited("Reset Jitter RNG due to intermittent health test failure\n");
++ ret = -EAGAIN;
++ } else if (ret == -1) {
++ /* Handle other errors */
++ ret = -EINVAL;
++ }
++
+ spin_unlock(&rng->jent_lock);
+
+ return ret;
+@@ -182,15 +204,31 @@ static int __init jent_mod_init(void)
+
+ ret = jent_entropy_init();
+ if (ret) {
++ /* Handle permanent health test error */
++ if (fips_enabled)
++ panic("jitterentropy: Initialization failed with host not compliant with requirements: %d\n", ret);
++
+ pr_info("jitterentropy: Initialization failed with host not compliant with requirements: %d\n", ret);
+ return -EFAULT;
+ }
++
++#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG
++ ret = jent_dbg_init();
++#endif
++ if(ret)
++ return ret;
++ printk("Debug interface error\n");
+ return crypto_register_rng(&jent_alg);
++
+ }
+
+ static void __exit jent_mod_exit(void)
+ {
+ crypto_unregister_rng(&jent_alg);
++
++#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_DEBUG
++ jent_dbg_exit();
++#endif
+ }
+
+ module_init(jent_mod_init);
+diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c
+index 77fa2120f..fea7a6d42 100644
+--- a/crypto/jitterentropy.c
++++ b/crypto/jitterentropy.c
+@@ -2,12 +2,12 @@
+ * Non-physical true random number generator based on timing jitter --
+ * Jitter RNG standalone code.
+ *
+- * Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2019
++ * Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2020
+ *
+ * Design
+ * ======
+ *
+- * See http://www.chronox.de/jent.html
++ * See https://www.chronox.de/jent.html
+ *
+ * License
+ * =======
+@@ -47,7 +47,7 @@
+
+ /*
+ * This Jitterentropy RNG is based on the jitterentropy library
+- * version 2.1.2 provided at http://www.chronox.de/jent.html
++ * version 2.2.0 provided at https://www.chronox.de/jent.html
+ */
+
+ #ifdef __OPTIMIZE__
+@@ -58,32 +58,8 @@ typedef unsigned long long __u64;
+ typedef long long __s64;
+ typedef unsigned int __u32;
+ #define NULL ((void *) 0)
++#include "jitterentropy.h"
+
+-/* The entropy pool */
+-struct rand_data {
+- /* all data values that are vital to maintain the security
+- * of the RNG are marked as SENSITIVE. A user must not
+- * access that information while the RNG executes its loops to
+- * calculate the next random value. */
+- __u64 data; /* SENSITIVE Actual random number */
+- __u64 old_data; /* SENSITIVE Previous random number */
+- __u64 prev_time; /* SENSITIVE Previous time stamp */
+-#define DATA_SIZE_BITS ((sizeof(__u64)) * 8)
+- __u64 last_delta; /* SENSITIVE stuck test */
+- __s64 last_delta2; /* SENSITIVE stuck test */
+- unsigned int osr; /* Oversample rate */
+-#define JENT_MEMORY_BLOCKS 64
+-#define JENT_MEMORY_BLOCKSIZE 32
+-#define JENT_MEMORY_ACCESSLOOPS 128
+-#define JENT_MEMORY_SIZE (JENT_MEMORY_BLOCKS*JENT_MEMORY_BLOCKSIZE)
+- unsigned char *mem; /* Memory access location with size of
+- * memblocks * memblocksize */
+- unsigned int memlocation; /* Pointer to byte in *mem */
+- unsigned int memblocks; /* Number of memory blocks in *mem */
+- unsigned int memblocksize; /* Size of one memory block in bytes */
+- unsigned int memaccessloops; /* Number of memory accesses per random
+- * bit generation */
+-};
+
+ /* Flags that can be used to initialize the RNG */
+ #define JENT_DISABLE_MEMORY_ACCESS (1<<2) /* Disable memory access for more
+@@ -98,19 +74,187 @@ struct rand_data {
+ * variations (2nd derivation of time is
+ * zero). */
+ #define JENT_ESTUCK 8 /* Too many stuck results during init. */
++#define JENT_EHEALTH 9 /* Health test failed during initialization */
++
++/*
++ * The output n bits can receive more than n bits of min entropy, of course,
++ * but the fixed output of the conditioning function can only asymptotically
++ * approach the output size bits of min entropy, not attain that bound. Random
++ * maps will tend to have output collisions, which reduces the creditable
++ * output entropy (that is what SP 800-90B Section 3.1.5.1.2 attempts to bound).
++ *
++ * The value "64" is justified in Appendix A.4 of the current 90C draft,
++ * and aligns with NIST's in "epsilon" definition in this document, which is
++ * that a string can be considered "full entropy" if you can bound the min
++ * entropy in each bit of output to at least 1-epsilon, where epsilon is
++ * required to be <= 2^(-32).
++ */
++#define JENT_ENTROPY_SAFETY_FACTOR 64
++
++#include <linux/fips.h>
++#include <linux/printk.h>
++
++/***************************************************************************
++ * Adaptive Proportion Test
++ *
++ * This test complies with SP800-90B section 4.4.2.
++ ***************************************************************************/
++
++/*
++ * Reset the APT counter
++ *
++ * @ec [in] Reference to entropy collector
++ */
++static void jent_apt_reset(struct rand_data *ec, unsigned int delta_masked)
++{
++ /* Reset APT counter */
++ ec->apt_count = 0;
++ ec->apt_base = delta_masked;
++ ec->apt_observations = 0;
++}
++
++/*
++ * Insert a new entropy event into APT
++ *
++ * @ec [in] Reference to entropy collector
++ * @delta_masked [in] Masked time delta to process
++ */
++static void jent_apt_insert(struct rand_data *ec, unsigned int delta_masked)
++{
++ /* Initialize the base reference */
++ if (!ec->apt_base_set) {
++ ec->apt_base = delta_masked;
++ ec->apt_base_set = 1;
++ return;
++ }
++
++ if (delta_masked == ec->apt_base)
++ ec->apt_count++;
++
++ ec->apt_observations++;
++
++ if (ec->apt_observations >= JENT_APT_WINDOW_SIZE)
++ jent_apt_reset(ec, delta_masked);
++}
++
++/* APT health test failure detection */
++static int jent_apt_permanent_failure(struct rand_data *ec)
++{
++ return (ec->apt_count >= JENT_APT_CUTOFF_PERMANENT) ? 1 : 0;
++}
++
++static int jent_apt_failure(struct rand_data *ec)
++{
++ return (ec->apt_count >= JENT_APT_CUTOFF) ? 1 : 0;
++}
+
+ /***************************************************************************
+- * Helper functions
++ * Stuck Test and its use as Repetition Count Test
++ *
++ * The Jitter RNG uses an enhanced version of the Repetition Count Test
++ * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
++ * back-to-back values, the input to the RCT is the counting of the stuck
++ * values during the generation of one Jitter RNG output block.
++ *
++ * The RCT is applied with an alpha of 2^{-30} compliant to FIPS 140-2 IG 9.8.
++ *
++ * During the counting operation, the Jitter RNG always calculates the RCT
++ * cut-off value of C. If that value exceeds the allowed cut-off value,
++ * the Jitter RNG output block will be calculated completely but discarded at
++ * the end. The caller of the Jitter RNG is informed with an error code.
+ ***************************************************************************/
+
+-void jent_get_nstime(__u64 *out);
+-void *jent_zalloc(unsigned int len);
+-void jent_zfree(void *ptr);
+-int jent_fips_enabled(void);
+-void jent_panic(char *s);
+-void jent_memcpy(void *dest, const void *src, unsigned int n);
++/*
++ * Repetition Count Test as defined in SP800-90B section 4.4.1
++ *
++ * @ec [in] Reference to entropy collector
++ * @stuck [in] Indicator whether the value is stuck
++ */
++static void jent_rct_insert(struct rand_data *ec, int stuck)
++{
++ if (stuck) {
++ ec->rct_count++;
++ } else {
++ /* Reset RCT */
++ ec->rct_count = 0;
++ }
++}
++
++static inline __u64 jent_delta(__u64 prev, __u64 next)
++{
++#define JENT_UINT64_MAX (__u64)(~((__u64) 0))
++ return (prev < next) ? (next - prev) :
++ (JENT_UINT64_MAX - prev + 1 + next);
++}
++
++/*
++ * Stuck test by checking the:
++ * 1st derivative of the jitter measurement (time delta)
++ * 2nd derivative of the jitter measurement (delta of time deltas)
++ * 3rd derivative of the jitter measurement (delta of delta of time deltas)
++ *
++ * All values must always be non-zero.
++ *
++ * @ec [in] Reference to entropy collector
++ * @current_delta [in] Jitter time delta
++ *
++ * @return
++ * 0 jitter measurement not stuck (good bit)
++ * 1 jitter measurement stuck (reject bit)
++ */
++static int jent_stuck(struct rand_data *ec, __u64 current_delta)
++{
++ __u64 delta2 = jent_delta(ec->last_delta, current_delta);
++ __u64 delta3 = jent_delta(ec->last_delta2, delta2);
++
++ ec->last_delta = current_delta;
++ ec->last_delta2 = delta2;
++
++ /*
++ * Insert the result of the comparison of two back-to-back time
++ * deltas.
++ */
++ jent_apt_insert(ec, current_delta);
++
++ if (!current_delta || !delta2 || !delta3) {
++ /* RCT with a stuck bit */
++ jent_rct_insert(ec, 1);
++ return 1;
++ }
++
++ /* RCT with a non-stuck bit */
++ jent_rct_insert(ec, 0);
++
++ return 0;
++}
++
++/* RCT health test failure detection */
++static int jent_rct_permanent_failure(struct rand_data *ec)
++{
++ return (ec->rct_count >= JENT_RCT_CUTOFF_PERMANENT) ? 1 : 0;
++}
++
++static int jent_rct_failure(struct rand_data *ec)
++{
++ return (ec->rct_count >= JENT_RCT_CUTOFF) ? 1 : 0;
++}
++
++/* Report of health test failures */
++static int jent_health_failure(struct rand_data *ec)
++{
++ return jent_rct_failure(ec) | jent_apt_failure(ec);
++}
++
++static int jent_permanent_health_failure(struct rand_data *ec)
++{
++ return jent_rct_permanent_failure(ec) | jent_apt_permanent_failure(ec);
++}
++
++/***************************************************************************
++ * Noise sources
++ ***************************************************************************/
+
+-/**
++/*
+ * Update of the loop count used for the next round of
+ * an entropy collection.
+ *
+@@ -153,11 +297,7 @@ static __u64 jent_loop_shuffle(struct rand_data *ec,
+ return (shuffle + (1<<min));
+ }
+
+-/***************************************************************************
+- * Noise sources
+- ***************************************************************************/
+-
+-/**
++/*
+ * CPU Jitter noise source -- this is the noise source based on the CPU
+ * execution time jitter
+ *
+@@ -171,18 +311,19 @@ static __u64 jent_loop_shuffle(struct rand_data *ec,
+ * the CPU execution time jitter. Any change to the loop in this function
+ * implies that careful retesting must be done.
+ *
+- * Input:
+- * @ec entropy collector struct -- may be NULL
+- * @time time stamp to be injected
+- * @loop_cnt if a value not equal to 0 is set, use the given value as number of
+- * loops to perform the folding
++ * @ec [in] entropy collector struct
++ * @time [in] time stamp to be injected
++ * @loop_cnt [in] if a value not equal to 0 is set, use the given value as
++ * number of loops to perform the folding
++ * @stuck [in] Is the time stamp identified as stuck?
+ *
+ * Output:
+ * updated ec->data
+ *
+ * @return Number of loops the folding operation is performed
+ */
+-static __u64 jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt)
++void jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt,
++ int stuck)
+ {
+ unsigned int i;
+ __u64 j = 0;
+@@ -225,12 +366,20 @@ static __u64 jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt)
+ new ^= tmp;
+ }
+ }
+- ec->data = new;
+
+- return fold_loop_cnt;
++ /*
++ * If the time stamp is stuck, do not finally insert the value into
++ * the entropy pool. Although this operation should not do any harm
++ * even when the time stamp has no entropy, SP800-90B requires that
++ * any conditioning operation (SP800-90B considers the LFSR to be a
++ * conditioning operation) to have an identical amount of input
++ * data according to section 3.1.5.
++ */
++ if (!stuck)
++ ec->data = new;
+ }
+
+-/**
++/*
+ * Memory Access noise source -- this is a noise source based on variations in
+ * memory access times
+ *
+@@ -248,16 +397,13 @@ static __u64 jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt)
+ * to reliably access either L3 or memory, the ec->mem memory must be quite
+ * large which is usually not desirable.
+ *
+- * Input:
+- * @ec Reference to the entropy collector with the memory access data -- if
+- * the reference to the memory block to be accessed is NULL, this noise
+- * source is disabled
+- * @loop_cnt if a value not equal to 0 is set, use the given value as number of
+- * loops to perform the folding
+- *
+- * @return Number of memory access operations
++ * @ec [in] Reference to the entropy collector with the memory access data -- if
++ * the reference to the memory block to be accessed is NULL, this noise
++ * source is disabled
++ * @loop_cnt [in] if a value not equal to 0 is set, use the given value
++ * number of loops to perform the LFSR
+ */
+-static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
++static void jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
+ {
+ unsigned int wrap = 0;
+ __u64 i = 0;
+@@ -267,7 +413,7 @@ static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
+ jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT);
+
+ if (NULL == ec || NULL == ec->mem)
+- return 0;
++ return;
+ wrap = ec->memblocksize * ec->memblocks;
+
+ /*
+@@ -293,44 +439,12 @@ static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
+ ec->memlocation = ec->memlocation + ec->memblocksize - 1;
+ ec->memlocation = ec->memlocation % wrap;
+ }
+- return i;
+ }
+
+ /***************************************************************************
+ * Start of entropy processing logic
+ ***************************************************************************/
+-
+-/**
+- * Stuck test by checking the:
+- * 1st derivation of the jitter measurement (time delta)
+- * 2nd derivation of the jitter measurement (delta of time deltas)
+- * 3rd derivation of the jitter measurement (delta of delta of time deltas)
+- *
+- * All values must always be non-zero.
+- *
+- * Input:
+- * @ec Reference to entropy collector
+- * @current_delta Jitter time delta
+- *
+- * @return
+- * 0 jitter measurement not stuck (good bit)
+- * 1 jitter measurement stuck (reject bit)
+- */
+-static int jent_stuck(struct rand_data *ec, __u64 current_delta)
+-{
+- __s64 delta2 = ec->last_delta - current_delta;
+- __s64 delta3 = delta2 - ec->last_delta2;
+-
+- ec->last_delta = current_delta;
+- ec->last_delta2 = delta2;
+-
+- if (!current_delta || !delta2 || !delta3)
+- return 1;
+-
+- return 0;
+-}
+-
+-/**
++/*
+ * This is the heart of the entropy generation: calculate time deltas and
+ * use the CPU jitter in the time deltas. The jitter is injected into the
+ * entropy pool.
+@@ -339,15 +453,15 @@ static int jent_stuck(struct rand_data *ec, __u64 current_delta)
+ * of this function! This can be done by calling this function
+ * and not using its result.
+ *
+- * Input:
+- * @entropy_collector Reference to entropy collector
++ * @ec [in] Reference to entropy collector
+ *
+ * @return result of stuck test
+ */
+-static int jent_measure_jitter(struct rand_data *ec)
++int jent_measure_jitter(struct rand_data *ec)
+ {
+ __u64 time = 0;
+ __u64 current_delta = 0;
++ int stuck;
+
+ /* Invoke one noise source before time measurement to add variations */
+ jent_memaccess(ec, 0);
+@@ -357,31 +471,33 @@ static int jent_measure_jitter(struct rand_data *ec)
+ * invocation to measure the timing variations
+ */
+ jent_get_nstime(&time);
+- current_delta = time - ec->prev_time;
++ current_delta = jent_delta(ec->prev_time, time);
+ ec->prev_time = time;
++ /* Check whether we have a stuck measurement. */
++ stuck = jent_stuck(ec, current_delta);
+
+ /* Now call the next noise sources which also injects the data */
+- jent_lfsr_time(ec, current_delta, 0);
+-
+- /* Check whether we have a stuck measurement. */
+- return jent_stuck(ec, current_delta);
++ jent_lfsr_time(ec, current_delta, 0, stuck);
++ return stuck;
+ }
+
+-/**
++/*
+ * Generator of one 64 bit random number
+ * Function fills rand_data->data
+ *
+- * Input:
+- * @ec Reference to entropy collector
++ * @ec [in] Reference to entropy collector
+ */
+ static void jent_gen_entropy(struct rand_data *ec)
+ {
+- unsigned int k = 0;
++ unsigned int k = 0, safety_factor = 0;
++
++ if (fips_enabled)
++ safety_factor = JENT_ENTROPY_SAFETY_FACTOR;
+
+ /* priming of the ->prev_time value */
+ jent_measure_jitter(ec);
+
+- while (1) {
++ while (!jent_health_failure(ec)) {
+ /* If a stuck measurement is received, repeat measurement */
+ if (jent_measure_jitter(ec))
+ continue;
+@@ -390,37 +506,12 @@ static void jent_gen_entropy(struct rand_data *ec)
+ * We multiply the loop value with ->osr to obtain the
+ * oversampling rate requested by the caller
+ */
+- if (++k >= (DATA_SIZE_BITS * ec->osr))
++ if (++k >= ((DATA_SIZE_BITS + safety_factor) * ec->osr))
+ break;
+ }
+ }
+
+-/**
+- * The continuous test required by FIPS 140-2 -- the function automatically
+- * primes the test if needed.
+- *
+- * Return:
+- * 0 if FIPS test passed
+- * < 0 if FIPS test failed
+- */
+-static void jent_fips_test(struct rand_data *ec)
+-{
+- if (!jent_fips_enabled())
+- return;
+-
+- /* prime the FIPS test */
+- if (!ec->old_data) {
+- ec->old_data = ec->data;
+- jent_gen_entropy(ec);
+- }
+-
+- if (ec->data == ec->old_data)
+- jent_panic("jitterentropy: Duplicate output detected\n");
+-
+- ec->old_data = ec->data;
+-}
+-
+-/**
++/*
+ * Entry function: Obtain entropy for the caller.
+ *
+ * This function invokes the entropy gathering logic as often to generate
+@@ -430,42 +521,64 @@ static void jent_fips_test(struct rand_data *ec)
+ * This function truncates the last 64 bit entropy value output to the exact
+ * size specified by the caller.
+ *
+- * Input:
+- * @ec Reference to entropy collector
+- * @data pointer to buffer for storing random data -- buffer must already
+- * exist
+- * @len size of the buffer, specifying also the requested number of random
+- * in bytes
++ * @ec [in] Reference to entropy collector
++ * @data [in] pointer to buffer for storing random data -- buffer must already
++ * exist
++ * @len [in] size of the buffer, specifying also the requested number of random
++ * in bytes
+ *
+ * @return 0 when request is fulfilled or an error
+ *
+ * The following error codes can occur:
+ * -1 entropy_collector is NULL
++ * -2 Intermittent health failure
++ * -3 Permanent health failure
+ */
+ int jent_read_entropy(struct rand_data *ec, unsigned char *data,
+ unsigned int len)
+ {
++ int ret = 0;
+ unsigned char *p = data;
+
+ if (!ec)
+ return -1;
+
+- while (0 < len) {
++ while (len > 0) {
+ unsigned int tocopy;
+
+ jent_gen_entropy(ec);
+- jent_fips_test(ec);
++
++ if (jent_permanent_health_failure(ec)) {
++ /*
++ * At this point, the Jitter RNG instance is considered
++ * as a failed instance. There is no rerun of the
++ * startup test any more, because the caller
++ * is assumed to not further use this instance.
++ */
++ return -3;
++ } else if (jent_health_failure(ec)) {
++ /*
++ * Perform startup health tests and return permanent
++ * error if it fails.
++ */
++ if (jent_entropy_init())
++ return -3;
++
++ return -2;
++ }
++
+ if ((DATA_SIZE_BITS / 8) < len)
+ tocopy = (DATA_SIZE_BITS / 8);
+ else
+ tocopy = len;
+ jent_memcpy(p, &ec->data, tocopy);
+
++ ret = ret + tocopy;
+ len -= tocopy;
+ p += tocopy;
+ }
+
+- return 0;
++ return ret;
+ }
+
+ /***************************************************************************
+@@ -496,7 +609,7 @@ struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
+ }
+
+ /* verify and set the oversampling rate */
+- if (0 == osr)
++ if (osr == 0)
+ osr = 1; /* minimum sampling rate is 1 */
+ entropy_collector->osr = osr;
+
+@@ -518,11 +631,15 @@ int jent_entropy_init(void)
+ int i;
+ __u64 delta_sum = 0;
+ __u64 old_delta = 0;
++ unsigned int nonstuck = 0;
+ int time_backwards = 0;
+ int count_mod = 0;
+ int count_stuck = 0;
+ struct rand_data ec = { 0 };
+
++ /* Required for RCT */
++ ec.osr = 1;
++
+ /* We could perform statistical tests here, but the problem is
+ * that we only have a few loop counts to do testing. These
+ * loop counts may show some slight skew and we produce
+@@ -544,8 +661,10 @@ int jent_entropy_init(void)
+ /*
+ * TESTLOOPCOUNT needs some loops to identify edge systems. 100 is
+ * definitely too little.
++ *
++ * SP800-90B requires at least 1024 initial test cycles.
+ */
+-#define TESTLOOPCOUNT 300
++#define TESTLOOPCOUNT 1024
+ #define CLEARCACHE 100
+ for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) {
+ __u64 time = 0;
+@@ -557,13 +676,13 @@ int jent_entropy_init(void)
+ /* Invoke core entropy collection logic */
+ jent_get_nstime(&time);
+ ec.prev_time = time;
+- jent_lfsr_time(&ec, time, 0);
++ jent_lfsr_time(&ec, time, 0, 0);
+ jent_get_nstime(&time2);
+
+ /* test whether timer works */
+ if (!time || !time2)
+ return JENT_ENOTIME;
+- delta = time2 - time;
++ delta = jent_delta(time, time2);
+ /*
+ * test whether timer is fine grained enough to provide
+ * delta even when called shortly after each other -- this
+@@ -581,11 +700,31 @@ int jent_entropy_init(void)
+ * etc. with the goal to clear it to get the worst case
+ * measurements.
+ */
+- if (CLEARCACHE > i)
++ if (i < CLEARCACHE)
+ continue;
+
+ if (stuck)
+ count_stuck++;
++ else {
++ nonstuck++;
++
++ /*
++ * Ensure that the APT succeeded.
++ *
++ * With the check below that count_stuck must be less
++ * than 10% of the overall generated raw entropy values
++ * it is guaranteed that the APT is invoked at
++ * floor((TESTLOOPCOUNT * 0.9) / 64) == 14 times.
++ */
++ if ((nonstuck % JENT_APT_WINDOW_SIZE) == 0) {
++ jent_apt_reset(&ec,
++ delta & JENT_APT_WORD_MASK);
++ }
++ }
++
++ /* Validate health test result */
++ if (jent_health_failure(&ec))
++ return JENT_EHEALTH;
+
+ /* test whether we have an increasing timer */
+ if (!(time2 > time))
+@@ -616,7 +755,7 @@ int jent_entropy_init(void)
+ * should not fail. The value of 3 should cover the NTP case being
+ * performed during our test run.
+ */
+- if (3 < time_backwards)
++ if (time_backwards > 3)
+ return JENT_ENOMONOTONIC;
+
+ /*
+diff --git a/crypto/jitterentropy.h b/crypto/jitterentropy.h
+new file mode 100644
+index 000000000..ee555f642
+--- /dev/null
++++ b/crypto/jitterentropy.h
+@@ -0,0 +1,79 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++#ifndef _JITTERENTROPY_H
++#define _JITTERENTROPY_H
++#include <linux/types.h>
++
++/* Flags that can be used to initialize the RNG */
++#define JENT_DISABLE_STIR (1<<0) /* Disable stirring the entropy pool */
++#define JENT_DISABLE_UNBIAS (1<<1) /* Disable the Von-Neuman Unbiaser */
++#define JENT_DISABLE_MEMORY_ACCESS (1<<2) /* Disable memory access for more
++ entropy, saves MEMORY_SIZE RAM for
++ entropy collector */
++#define DRIVER_NAME "jitterentropy"
++
++struct rand_data {
++ /* all data values that are vital to maintain the security
++ * of the RNG are marked as SENSITIVE. A user must not
++ * access that information while the RNG executes its loops to
++ * calculate the next random value. */
++ __u64 data; /* SENSITIVE Actual random number */
++ __u64 old_data; /* SENSITIVE Previous random number */
++ __u64 prev_time; /* SENSITIVE Previous time stamp */
++#define DATA_SIZE_BITS ((sizeof(__u64)) * 8)
++ __u64 last_delta; /* SENSITIVE stuck test */
++ __s64 last_delta2; /* SENSITIVE stuck test */
++ unsigned int osr; /* Oversample rate */
++#define JENT_MEMORY_BLOCKS 64
++#define JENT_MEMORY_BLOCKSIZE 32
++#define JENT_MEMORY_ACCESSLOOPS 128
++#define JENT_MEMORY_SIZE (JENT_MEMORY_BLOCKS*JENT_MEMORY_BLOCKSIZE)
++ unsigned char *mem; /* Memory access location with size of
++ * memblocks * memblocksize */
++ unsigned int memlocation; /* Pointer to byte in *mem */
++ unsigned int memblocks; /* Number of memory blocks in *mem */
++ unsigned int memblocksize; /* Size of one memory block in bytes */
++ unsigned int memaccessloops; /* Number of memory accesses per random
++ * bit generation */
++
++ /* Repetition Count Test */
++ unsigned int rct_count; /* Number of stuck values */
++
++ /* Intermittent health test failure threshold of 2^-30 */
++#define JENT_RCT_CUTOFF 30 /* Taken from SP800-90B sec 4.4.1 */
++#define JENT_APT_CUTOFF 325 /* Taken from SP800-90B sec 4.4.2 */
++ /* Permanent health test failure threshold of 2^-60 */
++#define JENT_RCT_CUTOFF_PERMANENT 60
++#define JENT_APT_CUTOFF_PERMANENT 355
++#define JENT_APT_WINDOW_SIZE 512 /* Data window size */
++ /* LSB of time stamp to process */
++#define JENT_APT_LSB 16
++#define JENT_APT_WORD_MASK (JENT_APT_LSB - 1)
++ unsigned int apt_observations; /* Number of collected observations */
++ unsigned int apt_count; /* APT counter */
++ unsigned int apt_base; /* APT base reference */
++ unsigned int apt_base_set:1; /* APT base reference set? */
++ unsigned int stir:1; /* Post-processing stirring */
++ unsigned int disable_unbias:1; /* Deactivate Von-Neuman unbias */
++};
++extern void *jent_zalloc(unsigned int len);
++extern void jent_zfree(void *ptr);
++extern void jent_memcpy(void *dest, const void *src, unsigned int n);
++extern void jent_get_nstime(__u64 *out);
++
++struct rand_data;
++extern int jent_entropy_init(void);
++extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
++ unsigned int len);
++
++extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
++ unsigned int flags);
++extern void jent_entropy_collector_free(struct rand_data *entropy_collector);
++
++unsigned int jent_version(void);
++
++void jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt, int stuck);
++
++int jent_measure_jitter(struct rand_data *ec);
++
++#endif /* _JITTERENTROPY_H */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1051-v5.10-backport-libkcapi.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1051-v5.10-backport-libkcapi.patch
new file mode 100644
index 0000000..0b196b6
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1051-v5.10-backport-libkcapi.patch
@@ -0,0 +1,376 @@
+diff --git a/crypto/af_alg.c b/crypto/af_alg.c
+index 4a2e91baa..fb6b4f8a0 100644
+--- a/crypto/af_alg.c
++++ b/crypto/af_alg.c
+@@ -226,6 +226,30 @@ static int alg_setkey(struct sock *sk, char __user *ukey,
+ return err;
+ }
+
++static int alg_setentropy(struct sock *sk, char __user *ukey,
++ unsigned int entropy_len)
++{
++ struct alg_sock *ask = alg_sk(sk);
++ const struct af_alg_type *type = ask->type;
++ u8 *entropy;
++ int err;
++
++ entropy = sock_kmalloc(sk, entropy_len, GFP_KERNEL);
++ if (!entropy)
++ return -ENOMEM;
++
++ err = -EFAULT;
++ if (copy_from_user(entropy, ukey, entropy_len))
++ goto out;
++
++ err = type->setentropy(ask->private, entropy, entropy_len);
++
++out:
++ sock_kzfree_s(sk, entropy, entropy_len);
++
++ return err;
++}
++
+ static int alg_setsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, unsigned int optlen)
+ {
+@@ -250,7 +274,6 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
+ goto unlock;
+ if (!type->setkey)
+ goto unlock;
+-
+ err = alg_setkey(sk, optval, optlen);
+ break;
+ case ALG_SET_AEAD_AUTHSIZE:
+@@ -259,6 +282,15 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
+ if (!type->setauthsize)
+ goto unlock;
+ err = type->setauthsize(ask->private, optlen);
++ break;
++ case ALG_SET_DRBG_ENTROPY:
++ if (sock->state == SS_CONNECTED)
++ goto unlock;
++ if (!type->setentropy)
++ goto unlock;
++ err = alg_setentropy(sk, optval, optlen);
++ break;
++
+ }
+
+ unlock:
+@@ -291,6 +323,11 @@ int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern)
+ security_sock_graft(sk2, newsock);
+ security_sk_clone(sk, sk2);
+
++ /*
++ * newsock->ops assigned here to allow type->accept call to override
++ * them when required.
++ */
++ newsock->ops = type->ops;
+ err = type->accept(ask->private, sk2);
+
+ nokey = err == -ENOKEY;
+@@ -309,7 +346,6 @@ int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern)
+ alg_sk(sk2)->parent = sk;
+ alg_sk(sk2)->type = type;
+
+- newsock->ops = type->ops;
+ newsock->state = SS_CONNECTED;
+
+ if (nokey)
+diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c
+index 22df3799a..bce3aef53 100644
+--- a/crypto/algif_rng.c
++++ b/crypto/algif_rng.c
+@@ -38,6 +38,7 @@
+ * DAMAGE.
+ */
+
++#include <linux/capability.h>
+ #include <linux/module.h>
+ #include <crypto/rng.h>
+ #include <linux/random.h>
+@@ -53,15 +54,26 @@ struct rng_ctx {
+ #define MAXSIZE 128
+ unsigned int len;
+ struct crypto_rng *drng;
++ u8 *addtl;
++ size_t addtl_len;
+ };
+
+-static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+- int flags)
++struct rng_parent_ctx {
++ struct crypto_rng *drng;
++ u8 *entropy;
++};
++
++static void rng_reset_addtl(struct rng_ctx *ctx)
+ {
+- struct sock *sk = sock->sk;
+- struct alg_sock *ask = alg_sk(sk);
+- struct rng_ctx *ctx = ask->private;
+- int err = -EFAULT;
++ kzfree(ctx->addtl);
++ ctx->addtl = NULL;
++ ctx->addtl_len = 0;
++}
++
++static int _rng_recvmsg(struct crypto_rng *drng, struct msghdr *msg, size_t len,
++ u8 *addtl, size_t addtl_len)
++{
++ int err = 0;
+ int genlen = 0;
+ u8 result[MAXSIZE];
+
+@@ -82,7 +94,7 @@ static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+ * seeding as they automatically seed. The X9.31 DRNG will return
+ * an error if it was not seeded properly.
+ */
+- genlen = crypto_rng_get_bytes(ctx->drng, result, len);
++ genlen = crypto_rng_generate(drng, addtl, addtl_len, result, len);
+ if (genlen < 0)
+ return genlen;
+
+@@ -92,6 +104,63 @@ static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+ return err ? err : len;
+ }
+
++static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
++ int flags)
++{
++ struct sock *sk = sock->sk;
++ struct alg_sock *ask = alg_sk(sk);
++ struct rng_ctx *ctx = ask->private;
++
++ return _rng_recvmsg(ctx->drng, msg, len, NULL, 0);
++}
++
++static int rng_test_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
++ int flags)
++{
++ struct sock *sk = sock->sk;
++ struct alg_sock *ask = alg_sk(sk);
++ struct rng_ctx *ctx = ask->private;
++ int ret;
++
++ lock_sock(sock->sk);
++ ret = _rng_recvmsg(ctx->drng, msg, len, ctx->addtl, ctx->addtl_len);
++ rng_reset_addtl(ctx);
++ release_sock(sock->sk);
++
++ return ret;
++}
++
++static int rng_test_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
++{
++ int err;
++ struct alg_sock *ask = alg_sk(sock->sk);
++ struct rng_ctx *ctx = ask->private;
++
++ lock_sock(sock->sk);
++ if (len > MAXSIZE) {
++ err = -EMSGSIZE;
++ goto unlock;
++ }
++
++ rng_reset_addtl(ctx);
++ ctx->addtl = kmalloc(len, GFP_KERNEL);
++ if (!ctx->addtl) {
++ err = -ENOMEM;
++ goto unlock;
++ }
++
++ err = memcpy_from_msg(ctx->addtl, msg, len);
++ if (err) {
++ rng_reset_addtl(ctx);
++ goto unlock;
++ }
++ ctx->addtl_len = len;
++
++unlock:
++ release_sock(sock->sk);
++ return err ? err : len;
++}
++
+ static struct proto_ops algif_rng_ops = {
+ .family = PF_ALG,
+
+@@ -113,14 +182,53 @@ static struct proto_ops algif_rng_ops = {
+ .recvmsg = rng_recvmsg,
+ };
+
++static struct proto_ops __maybe_unused algif_rng_test_ops = {
++ .family = PF_ALG,
++
++ .connect = sock_no_connect,
++ .socketpair = sock_no_socketpair,
++ .getname = sock_no_getname,
++ .ioctl = sock_no_ioctl,
++ .listen = sock_no_listen,
++ .shutdown = sock_no_shutdown,
++ .mmap = sock_no_mmap,
++ .bind = sock_no_bind,
++ .accept = sock_no_accept,
++ .sendpage = sock_no_sendpage,
++
++ .release = af_alg_release,
++ .recvmsg = rng_test_recvmsg,
++ .sendmsg = rng_test_sendmsg,
++};
++
+ static void *rng_bind(const char *name, u32 type, u32 mask)
+ {
+- return crypto_alloc_rng(name, type, mask);
++ struct rng_parent_ctx *pctx;
++ struct crypto_rng *rng;
++
++ pctx = kzalloc(sizeof(*pctx), GFP_KERNEL);
++ if (!pctx)
++ return ERR_PTR(-ENOMEM);
++
++ rng = crypto_alloc_rng(name, type, mask);
++ if (IS_ERR(rng)) {
++ kfree(pctx);
++ return ERR_CAST(rng);
++ }
++
++ pctx->drng = rng;
++ return pctx;
+ }
+
+ static void rng_release(void *private)
+ {
+- crypto_free_rng(private);
++ struct rng_parent_ctx *pctx = private;
++ if (unlikely(!pctx))
++ return;
++ crypto_free_rng(pctx->drng);
++ kzfree(pctx->entropy);
++ kzfree(pctx);
++ return;
+ }
+
+ static void rng_sock_destruct(struct sock *sk)
+@@ -128,6 +236,7 @@ static void rng_sock_destruct(struct sock *sk)
+ struct alg_sock *ask = alg_sk(sk);
+ struct rng_ctx *ctx = ask->private;
+
++ rng_reset_addtl(ctx);
+ sock_kfree_s(sk, ctx, ctx->len);
+ af_alg_release_parent(sk);
+ }
+@@ -135,6 +244,7 @@ static void rng_sock_destruct(struct sock *sk)
+ static int rng_accept_parent(void *private, struct sock *sk)
+ {
+ struct rng_ctx *ctx;
++ struct rng_parent_ctx *pctx = private;
+ struct alg_sock *ask = alg_sk(sk);
+ unsigned int len = sizeof(*ctx);
+
+@@ -143,6 +253,8 @@ static int rng_accept_parent(void *private, struct sock *sk)
+ return -ENOMEM;
+
+ ctx->len = len;
++ ctx->addtl = NULL;
++ ctx->addtl_len = 0;
+
+ /*
+ * No seeding done at that point -- if multiple accepts are
+@@ -150,20 +262,59 @@ static int rng_accept_parent(void *private, struct sock *sk)
+ * state of the RNG.
+ */
+
+- ctx->drng = private;
++ ctx->drng = pctx->drng;
+ ask->private = ctx;
+ sk->sk_destruct = rng_sock_destruct;
+
++ /*
++ * Non NULL pctx->entropy means that CAVP test has been initiated on
++ * this socket, replace proto_ops algif_rng_ops with algif_rng_test_ops.
++ */
++ if (IS_ENABLED(CONFIG_CRYPTO_USER_API_RNG_CAVP) && pctx->entropy)
++ sk->sk_socket->ops = &algif_rng_test_ops;
+ return 0;
+ }
+
+ static int rng_setkey(void *private, const u8 *seed, unsigned int seedlen)
+ {
++ struct rng_parent_ctx *pctx = private;
+ /*
+ * Check whether seedlen is of sufficient size is done in RNG
+ * implementations.
+ */
+- return crypto_rng_reset(private, seed, seedlen);
++ return crypto_rng_reset(pctx->drng, seed, seedlen);
++}
++
++static int __maybe_unused rng_setentropy(void *private, const u8 *entropy,
++ unsigned int len)
++{
++ struct rng_parent_ctx *pctx = private;
++ u8 *kentropy = NULL;
++ int i;
++
++ if (!capable(CAP_SYS_ADMIN))
++ return -EACCES;
++
++ if (pctx->entropy)
++ return -EINVAL;
++
++ if (len > MAXSIZE)
++ return -EMSGSIZE;
++
++ if (len) {
++ kentropy = (u8*)kmalloc(len, GFP_KERNEL);
++ memcpy(kentropy, entropy, len);
++ if (IS_ERR(kentropy))
++ return PTR_ERR(kentropy);
++ }
++
++ crypto_rng_alg(pctx->drng)->set_ent(pctx->drng, kentropy, len);
++ /*
++ * Since rng doesn't perform any memory management for the entropy
++ * buffer, save kentropy pointer to pctx now to free it after use.
++ */
++ pctx->entropy = kentropy;
++ return 0;
+ }
+
+ static const struct af_alg_type algif_type_rng = {
+@@ -173,7 +324,10 @@ static const struct af_alg_type algif_type_rng = {
+ .setkey = rng_setkey,
+ .ops = &algif_rng_ops,
+ .name = "rng",
+- .owner = THIS_MODULE
++ .owner = THIS_MODULE,
++#ifdef CONFIG_CRYPTO_USER_API_RNG_CAVP
++ .setentropy = rng_setentropy,
++#endif
+ };
+
+ static int __init rng_init(void)
+diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
+index c1a8d4a41..ca06787f7 100644
+--- a/include/crypto/if_alg.h
++++ b/include/crypto/if_alg.h
+@@ -46,6 +46,7 @@ struct af_alg_type {
+ void *(*bind)(const char *name, u32 type, u32 mask);
+ void (*release)(void *private);
+ int (*setkey)(void *private, const u8 *key, unsigned int keylen);
++ int (*setentropy)(void *private, const u8 *key, unsigned int keylen);
+ int (*accept)(void *private, struct sock *sk);
+ int (*accept_nokey)(void *private, struct sock *sk);
+ int (*setauthsize)(void *private, unsigned int authsize);
+diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
+index 769050771..dc52a11ba 100644
+--- a/include/uapi/linux/if_alg.h
++++ b/include/uapi/linux/if_alg.h
+@@ -51,6 +51,7 @@ struct af_alg_iv {
+ #define ALG_SET_OP 3
+ #define ALG_SET_AEAD_ASSOCLEN 4
+ #define ALG_SET_AEAD_AUTHSIZE 5
++#define ALG_SET_DRBG_ENTROPY 6
+
+ /* Operations */
+ #define ALG_OP_DECRYPT 0
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1700-macsec-revert-async-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1700-macsec-revert-async-support.patch
deleted file mode 100644
index 3212b6b..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1700-macsec-revert-async-support.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 8b45e5c6b6b419305ef893e1dfdd4c69c020958b Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:05:59 +0800
-Subject: [PATCH]
- [backport-networking-drivers][999-1700-macsec-revert-async-support.patch]
-
----
- drivers/net/macsec.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
-index f729f55f6..e3f03c89c 100644
---- a/drivers/net/macsec.c
-+++ b/drivers/net/macsec.c
-@@ -1311,8 +1311,7 @@ static struct crypto_aead *macsec_alloc_tfm(char *key, int key_len, int icv_len)
- struct crypto_aead *tfm;
- int ret;
-
-- /* Pick a sync gcm(aes) cipher to ensure order is preserved. */
-- tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
-+ tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
-
- if (IS_ERR(tfm))
- return tfm;
---
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1713-v5.15-net-dsa-add-dsa_port_from_netdev.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1713-v5.15-net-dsa-add-dsa_port_from_netdev.patch
new file mode 100644
index 0000000..1b3468d
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1713-v5.15-net-dsa-add-dsa_port_from_netdev.patch
@@ -0,0 +1,74 @@
+From b80c745d2b90b30558e4f5b12060af956ae8e76d Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Mon, 18 Sep 2023 10:52:27 +0800
+Subject: [PATCH] net dsa add dsa_port_from_netdev
+
+---
+ include/net/dsa.h | 10 +
+ net/dsa/dsa.c | 9 +
+ net/dsa/slave.c | 1 +
+ 3 files changed, 20 insertions(+), 0 deletions(-)
+
+diff --git a/include/net/dsa.h b/include/net/dsa.h
+index d29ee9e..43f65cb 100644
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -562,6 +562,8 @@ struct dsa_switch_ops {
+ struct sk_buff *skb);
+ };
+
++struct dsa_port *dsa_port_from_netdev(struct net_device *netdev);
++
+ struct dsa_switch_driver {
+ struct list_head list;
+ const struct dsa_switch_ops *ops;
+@@ -654,6 +656,14 @@ static inline int call_dsa_notifiers(unsigned long val, struct net_device *dev,
+ #define BRCM_TAG_GET_PORT(v) ((v) >> 8)
+ #define BRCM_TAG_GET_QUEUE(v) ((v) & 0xff)
+
++#if IS_ENABLED(CONFIG_NET_DSA)
++bool dsa_slave_dev_check(const struct net_device *dev);
++#else
++static inline bool dsa_slave_dev_check(const struct net_device *dev)
++{
++ return false;
++}
++#endif
+
+ netdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev);
+ int dsa_port_get_phy_strings(struct dsa_port *dp, uint8_t *data);
+diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
+index ca80f86..35a1249 100644
+--- a/net/dsa/dsa.c
++++ b/net/dsa/dsa.c
+@@ -329,6 +329,15 @@ int call_dsa_notifiers(unsigned long val, struct net_device *dev,
+ }
+ EXPORT_SYMBOL_GPL(call_dsa_notifiers);
+
++struct dsa_port *dsa_port_from_netdev(struct net_device *netdev)
++{
++ if (!netdev || !dsa_slave_dev_check(netdev))
++ return ERR_PTR(-ENODEV);
++
++ return dsa_slave_to_port(netdev);
++}
++EXPORT_SYMBOL_GPL(dsa_port_from_netdev);
++
+ static int __init dsa_init_module(void)
+ {
+ int rc;
+diff --git a/net/dsa/slave.c b/net/dsa/slave.c
+index e2b91b3..2dfaa1e 100644
+--- a/net/dsa/slave.c
++++ b/net/dsa/slave.c
+@@ -1499,6 +1533,7 @@ bool dsa_slave_dev_check(const struct net_device *dev)
+ {
+ return dev->netdev_ops == &dsa_slave_netdev_ops;
+ }
++EXPORT_SYMBOL_GPL(dsa_slave_dev_check);
+
+ static int dsa_slave_changeupper(struct net_device *dev,
+ struct netdev_notifier_changeupper_info *info)
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1714-v5.15-net-dsa-add-netdev_upper_dev_link.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1714-v5.15-net-dsa-add-netdev_upper_dev_link.patch
new file mode 100644
index 0000000..2b854c4
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1714-v5.15-net-dsa-add-netdev_upper_dev_link.patch
@@ -0,0 +1,36 @@
+From 120baca4e8b019d03c8d1a29012cea911629247a Mon Sep 17 00:00:00 2001
+From: Bc-bocun Chen <bc-bocun.chen@mediatek.com>
+Date: Mon, 18 Sep 2023 11:13:51 +0800
+Subject: [PATCH] net dsa add netdev_upper_dev_link
+
+---
+ net/dsa/slave.c | 11 +
+ 1 files changed, 11 insertions(+), 0 deletions(-)
+
+diff --git a/net/dsa/slave.c b/net/dsa/slave.c
+index 2dfaa1e..a60a26c 100644
+--- a/net/dsa/slave.c
++++ b/net/dsa/slave.c
+@@ -1495,8 +1495,19 @@ int dsa_slave_create(struct dsa_port *port)
+ goto out_phy;
+ }
+
++ rtnl_lock();
++
++ ret = netdev_upper_dev_link(master, slave_dev, NULL);
++
++ rtnl_unlock();
++
++ if (ret)
++ goto out_unregister;
++
+ return 0;
+
++out_unregister:
++ unregister_netdev(slave_dev);
+ out_phy:
+ rtnl_lock();
+ phylink_disconnect_phy(p->dp->pl);
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1800-v6.7-MT7986-ASoC-platform-driver.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1800-v6.7-MT7986-ASoC-platform-driver.patch
new file mode 100644
index 0000000..3c5096a
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1800-v6.7-MT7986-ASoC-platform-driver.patch
@@ -0,0 +1,1602 @@
+From 0dc695c6d7e86562bb185214a271a2d4614d3f96 Mon Sep 17 00:00:00 2001
+From: Maso Huang <maso.huang@mediatek.com>
+Date: Thu, 16 Nov 2023 12:05:02 +0800
+Subject: [PATCH] v6.7 MT7986 ASoC platform driver
+
+---
+ sound/soc/mediatek/Kconfig | 20 +
+ sound/soc/mediatek/Makefile | 1 +
+ sound/soc/mediatek/mt7986/Makefile | 9 +
+ sound/soc/mediatek/mt7986/mt7986-afe-common.h | 49 ++
+ sound/soc/mediatek/mt7986/mt7986-afe-pcm.c | 640 ++++++++++++++++++
+ sound/soc/mediatek/mt7986/mt7986-dai-etdm.c | 428 ++++++++++++
+ sound/soc/mediatek/mt7986/mt7986-reg.h | 196 ++++++
+ sound/soc/mediatek/mt7986/mt7986-wm8960.c | 177 +++++
+ 8 files changed, 1520 insertions(+)
+ create mode 100644 sound/soc/mediatek/mt7986/Makefile
+ create mode 100644 sound/soc/mediatek/mt7986/mt7986-afe-common.h
+ create mode 100644 sound/soc/mediatek/mt7986/mt7986-afe-pcm.c
+ create mode 100644 sound/soc/mediatek/mt7986/mt7986-dai-etdm.c
+ create mode 100644 sound/soc/mediatek/mt7986/mt7986-reg.h
+ create mode 100644 sound/soc/mediatek/mt7986/mt7986-wm8960.c
+
+diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
+index 111e44b..99d36c4 100644
+--- a/sound/soc/mediatek/Kconfig
++++ b/sound/soc/mediatek/Kconfig
+@@ -53,6 +53,26 @@ 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_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
+diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile
+index 76032ca..657325a 100644
+--- a/sound/soc/mediatek/Makefile
++++ b/sound/soc/mediatek/Makefile
+@@ -2,5 +2,6 @@
+ 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/
+diff --git a/sound/soc/mediatek/mt7986/Makefile b/sound/soc/mediatek/mt7986/Makefile
+new file mode 100644
+index 0000000..fc4c825
+--- /dev/null
++++ b/sound/soc/mediatek/mt7986/Makefile
+@@ -0,0 +1,9 @@
++# 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
++obj-$(CONFIG_SND_SOC_MT7986_WM8960) += mt7986-wm8960.o
+diff --git a/sound/soc/mediatek/mt7986/mt7986-afe-common.h b/sound/soc/mediatek/mt7986/mt7986-afe-common.h
+new file mode 100644
+index 0000000..fc3bb31
+--- /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 <vic.wu@mediatek.com>
++ * Maso Huang <maso.huang@mediatek.com>
++ */
++
++#ifndef _MT_7986_AFE_COMMON_H_
++#define _MT_7986_AFE_COMMON_H_
++
++#include <sound/soc.h>
++#include <linux/clk.h>
++#include <linux/list.h>
++#include <linux/regmap.h>
++#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
+diff --git a/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c b/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c
+new file mode 100644
+index 0000000..e2f8c51
+--- /dev/null
++++ b/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c
+@@ -0,0 +1,640 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * MediaTek ALSA SoC AFE platform driver for MT7986
++ *
++ * Copyright (c) 2023 MediaTek Inc.
++ * Authors: Vic Wu <vic.wu@mediatek.com>
++ * Maso Huang <maso.huang@mediatek.com>
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/pm_runtime.h>
++
++#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) {
++ dev_err(afe->dev, "Failed to get clocks\n");
++ return ret;
++ }
++
++ 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) {
++ dev_err(afe->dev, "Failed to enable clocks\n");
++ return ret;
++ }
++
++ 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,
++ .ops = &mtk_afe_pcm_ops,
++ .pcm_new = mtk_afe_pcm_new,
++ .pcm_free = mtk_afe_pcm_free,
++ .probe = mt7986_afe_component_probe,
++};
++
++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) {
++ dev_err(dev, "Cannot initialize clocks\n");
++ return ret;
++ }
++
++ pm_runtime_enable(dev);
++
++ /* 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;
++ dev_err(dev, "No irq found\n");
++ return ret;
++ }
++ ret = devm_request_irq(dev, irq_id, mt7986_afe_irq_handler,
++ IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);
++ if (ret) {
++ dev_err(dev, "Failed to request irq for asys-isr\n");
++ return ret;
++ }
++
++ /* 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) {
++ dev_err(dev, "DAI register failed, i: %d\n", i);
++ return ret;
++ }
++ }
++
++ /* init dai_driver and component_driver */
++ ret = mtk_afe_combine_sub_dai(afe);
++ if (ret) {
++ dev_err(dev, "mtk_afe_combine_sub_dai fail\n");
++ return ret;
++ }
++
++ 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) {
++ dev_err(dev, "Cannot register AFE component\n");
++ return ret;
++ }
++
++ ret = devm_snd_soc_register_component(afe->dev,
++ &mt7986_afe_pcm_dai_component,
++ afe->dai_drivers,
++ afe->num_dai_drivers);
++ if (ret) {
++ dev_err(dev, "Cannot register PCM DAI component\n");
++ return ret;
++ }
++
++ return 0;
++}
++
++static int 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);
++
++ return 0;
++}
++
++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 = 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 <vic.wu@mediatek.com>");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/mediatek/mt7986/mt7986-dai-etdm.c b/sound/soc/mediatek/mt7986/mt7986-dai-etdm.c
+new file mode 100644
+index 0000000..192f55a
+--- /dev/null
++++ b/sound/soc/mediatek/mt7986/mt7986-dai-etdm.c
+@@ -0,0 +1,428 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * MediaTek ALSA SoC Audio DAI eTDM Control
++ *
++ * Copyright (c) 2023 MediaTek Inc.
++ * Authors: Vic Wu <vic.wu@mediatek.com>
++ * Maso Huang <maso.huang@mediatek.com>
++ */
++
++#include <linux/bitfield.h>
++#include <linux/bitops.h>
++#include <linux/regmap.h>
++#include <sound/pcm_params.h>
++#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) {
++ dev_err(afe->dev, "Failed to enable clocks\n");
++ return ret;
++ }
++
++ 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)
++{
++ unsigned int rate = params_rate(params);
++ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
++
++ 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,
++ 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_rates = 1,
++ .symmetric_samplebits = 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/sound/soc/mediatek/mt7986/mt7986-reg.h b/sound/soc/mediatek/mt7986/mt7986-reg.h
+new file mode 100644
+index 0000000..c2b2007
+--- /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 <vic.wu@mediatek.com>
++ * Maso Huang <maso.huang@mediatek.com>
++ */
++
++#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/sound/soc/mediatek/mt7986/mt7986-wm8960.c b/sound/soc/mediatek/mt7986/mt7986-wm8960.c
+new file mode 100644
+index 0000000..c1390b3
+--- /dev/null
++++ b/sound/soc/mediatek/mt7986/mt7986-wm8960.c
+@@ -0,0 +1,177 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * mt7986-wm8960.c -- MT7986-WM8960 ALSA SoC machine driver
++ *
++ * Copyright (c) 2023 MediaTek Inc.
++ * Authors: Vic Wu <vic.wu@mediatek.com>
++ * Maso Huang <maso.huang@mediatek.com>
++ */
++
++#include <linux/module.h>
++#include <sound/soc.h>
++
++#include "mt7986-afe-common.h"
++
++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 device_node *platform_dai_node, *codec_dai_node;
++ int ret, i;
++
++ card->dev = &pdev->dev;
++
++ platform = of_get_child_by_name(pdev->dev.of_node, "platform");
++
++ if (platform) {
++ platform_dai_node = of_parse_phandle(platform, "sound-dai", 0);
++ of_node_put(platform);
++
++ if (!platform_dai_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 = platform_dai_node;
++ }
++
++ codec = of_get_child_by_name(pdev->dev.of_node, "codec");
++
++ if (codec) {
++ codec_dai_node = of_parse_phandle(codec, "sound-dai", 0);
++ of_node_put(codec);
++
++ 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(platform_dai_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 = codec_dai_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(platform_dai_node);
++ of_node_put(codec_dai_node);
++ return ret;
++}
++
++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,
++};
++
++module_platform_driver(mt7986_wm8960_machine);
++
++/* Module information */
++MODULE_DESCRIPTION("MT7986 WM8960 ALSA SoC machine driver");
++MODULE_AUTHOR("Vic Wu <vic.wu@mediatek.com>");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("mt7986 wm8960 soc card");
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2210-v6.1-iio-adc-add-rtq6056-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1801-v6.1-iio-adc-add-rtq6056-support.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-2210-v6.1-iio-adc-add-rtq6056-support.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1801-v6.1-iio-adc-add-rtq6056-support.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1000-backport-pinctrl-pinconf-setting-combo.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1802-v6.4-backport-pinctrl-pinconf-setting-combo.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1000-backport-pinctrl-pinconf-setting-combo.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1802-v6.4-backport-pinctrl-pinconf-setting-combo.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1033-backport-pinctrl-spinlock.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1803-v6.6-pinctrl-spinlock.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1033-backport-pinctrl-spinlock.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1803-v6.6-pinctrl-spinlock.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1804-v6.4-leds-pwm-multicolor.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1804-v6.4-leds-pwm-multicolor.patch
new file mode 100644
index 0000000..ea1ab5c
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1804-v6.4-leds-pwm-multicolor.patch
@@ -0,0 +1,602 @@
+From 05c42f841f6d47f888f11c0ae016c217c3c81c7f Mon Sep 17 00:00:00 2001
+From: Maso Huang <maso.huang@mediatek.com>
+Date: Mon, 4 Dec 2023 19:16:12 +0800
+Subject: [PATCH] backport leds pwm multicolor from v6.4
+
+---
+ drivers/leds/Kconfig | 21 +++
+ drivers/leds/Makefile | 2 +
+ drivers/leds/led-class-multicolor.c | 203 +++++++++++++++++++++++++++
+ drivers/leds/leds-pwm-multicolor.c | 194 +++++++++++++++++++++++++
+ include/linux/led-class-multicolor.h | 109 ++++++++++++++
+ 5 files changed, 529 insertions(+)
+ create mode 100644 drivers/leds/led-class-multicolor.c
+ create mode 100644 drivers/leds/leds-pwm-multicolor.c
+ create mode 100644 include/linux/led-class-multicolor.h
+
+diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
+index db18084..eebfb8c 100644
+--- a/drivers/leds/Kconfig
++++ b/drivers/leds/Kconfig
+@@ -30,6 +30,16 @@ config LEDS_CLASS_FLASH
+ for the flash related features of a LED device. It can be built
+ as a module.
+
++config LEDS_CLASS_MULTICOLOR
++ tristate "LED Multicolor Class Support"
++ depends on LEDS_CLASS
++ help
++ This option enables the multicolor LED sysfs class in /sys/class/leds.
++ It wraps LED class and adds multicolor LED specific sysfs attributes
++ and kernel internal API to it. You'll need this to provide support
++ for multicolor LEDs that are grouped together. This class is not
++ intended for single color LEDs. It can be built as a module.
++
+ config LEDS_BRIGHTNESS_HW_CHANGED
+ bool "LED Class brightness_hw_changed attribute support"
+ depends on LEDS_CLASS
+@@ -518,6 +528,17 @@ config LEDS_PWM
+ help
+ This option enables support for pwm driven LEDs
+
++config LEDS_PWM_MULTICOLOR
++ tristate "PWM driven multi-color LED Support"
++ depends on LEDS_CLASS_MULTICOLOR
++ depends on PWM
++ help
++ This option enables support for PWM driven monochrome LEDs that are
++ grouped into multicolor LEDs.
++
++ To compile this driver as a module, choose M here: the module
++ will be called leds-pwm-multicolor.
++
+ config LEDS_REGULATOR
+ tristate "REGULATOR driven LED support"
+ depends on LEDS_CLASS
+diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
+index e648275..39885e5 100644
+--- a/drivers/leds/Makefile
++++ b/drivers/leds/Makefile
+@@ -4,6 +4,7 @@
+ obj-$(CONFIG_NEW_LEDS) += led-core.o
+ obj-$(CONFIG_LEDS_CLASS) += led-class.o
+ obj-$(CONFIG_LEDS_CLASS_FLASH) += led-class-flash.o
++obj-$(CONFIG_LEDS_CLASS_MULTICOLOR) += led-class-multicolor.o
+ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
+
+ # LED Platform Drivers
+@@ -54,6 +55,7 @@ obj-$(CONFIG_LEDS_DA9052) += leds-da9052.o
+ obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o
+ obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
+ obj-$(CONFIG_LEDS_PWM) += leds-pwm.o
++obj-$(CONFIG_LEDS_PWM_MULTICOLOR) += leds-pwm-multicolor.o
+ obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o
+ obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o
+ obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o
+diff --git a/drivers/leds/led-class-multicolor.c b/drivers/leds/led-class-multicolor.c
+new file mode 100644
+index 0000000..16f3372
+--- /dev/null
++++ b/drivers/leds/led-class-multicolor.c
+@@ -0,0 +1,203 @@
++// SPDX-License-Identifier: GPL-2.0
++// LED Multicolor class interface
++// Copyright (C) 2019-20 Texas Instruments Incorporated - http://www.ti.com/
++// Author: Dan Murphy <dmurphy@ti.com>
++
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/led-class-multicolor.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/uaccess.h>
++
++#include "leds.h"
++
++int led_mc_calc_color_components(struct led_classdev_mc *mcled_cdev,
++ enum led_brightness brightness)
++{
++ struct led_classdev *led_cdev = &mcled_cdev->led_cdev;
++ int i;
++
++ for (i = 0; i < mcled_cdev->num_colors; i++)
++ mcled_cdev->subled_info[i].brightness = brightness *
++ mcled_cdev->subled_info[i].intensity /
++ led_cdev->max_brightness;
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(led_mc_calc_color_components);
++
++static ssize_t multi_intensity_store(struct device *dev,
++ struct device_attribute *intensity_attr,
++ const char *buf, size_t size)
++{
++ struct led_classdev *led_cdev = dev_get_drvdata(dev);
++ struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev);
++ int nrchars, offset = 0;
++ int intensity_value[LED_COLOR_ID_MAX];
++ int i;
++ ssize_t ret;
++
++ mutex_lock(&led_cdev->led_access);
++
++ for (i = 0; i < mcled_cdev->num_colors; i++) {
++ ret = sscanf(buf + offset, "%i%n",
++ &intensity_value[i], &nrchars);
++ if (ret != 1) {
++ ret = -EINVAL;
++ goto err_out;
++ }
++ offset += nrchars;
++ }
++
++ offset++;
++ if (offset < size) {
++ ret = -EINVAL;
++ goto err_out;
++ }
++
++ for (i = 0; i < mcled_cdev->num_colors; i++)
++ mcled_cdev->subled_info[i].intensity = intensity_value[i];
++
++ led_set_brightness(led_cdev, led_cdev->brightness);
++ ret = size;
++err_out:
++ mutex_unlock(&led_cdev->led_access);
++ return ret;
++}
++
++static ssize_t multi_intensity_show(struct device *dev,
++ struct device_attribute *intensity_attr,
++ char *buf)
++{
++ struct led_classdev *led_cdev = dev_get_drvdata(dev);
++ struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev);
++ int len = 0;
++ int i;
++
++ for (i = 0; i < mcled_cdev->num_colors; i++) {
++ len += sprintf(buf + len, "%d",
++ mcled_cdev->subled_info[i].intensity);
++ if (i < mcled_cdev->num_colors - 1)
++ len += sprintf(buf + len, " ");
++ }
++
++ buf[len++] = '\n';
++ return len;
++}
++static DEVICE_ATTR_RW(multi_intensity);
++
++static ssize_t multi_index_show(struct device *dev,
++ struct device_attribute *multi_index_attr,
++ char *buf)
++{
++ struct led_classdev *led_cdev = dev_get_drvdata(dev);
++ struct led_classdev_mc *mcled_cdev = lcdev_to_mccdev(led_cdev);
++ int len = 0;
++ int index;
++ int i;
++
++ for (i = 0; i < mcled_cdev->num_colors; i++) {
++ index = mcled_cdev->subled_info[i].color_index;
++ len += sprintf(buf + len, "%s", led_colors[index]);
++ if (i < mcled_cdev->num_colors - 1)
++ len += sprintf(buf + len, " ");
++ }
++
++ buf[len++] = '\n';
++ return len;
++}
++static DEVICE_ATTR_RO(multi_index);
++
++static struct attribute *led_multicolor_attrs[] = {
++ &dev_attr_multi_intensity.attr,
++ &dev_attr_multi_index.attr,
++ NULL,
++};
++ATTRIBUTE_GROUPS(led_multicolor);
++
++int led_classdev_multicolor_register_ext(struct device *parent,
++ struct led_classdev_mc *mcled_cdev,
++ struct led_init_data *init_data)
++{
++ struct led_classdev *led_cdev;
++
++ if (!mcled_cdev)
++ return -EINVAL;
++
++ if (mcled_cdev->num_colors <= 0)
++ return -EINVAL;
++
++ if (mcled_cdev->num_colors > LED_COLOR_ID_MAX)
++ return -EINVAL;
++
++ led_cdev = &mcled_cdev->led_cdev;
++ mcled_cdev->led_cdev.groups = led_multicolor_groups;
++
++ return led_classdev_register_ext(parent, led_cdev, init_data);
++}
++EXPORT_SYMBOL_GPL(led_classdev_multicolor_register_ext);
++
++void led_classdev_multicolor_unregister(struct led_classdev_mc *mcled_cdev)
++{
++ if (!mcled_cdev)
++ return;
++
++ led_classdev_unregister(&mcled_cdev->led_cdev);
++}
++EXPORT_SYMBOL_GPL(led_classdev_multicolor_unregister);
++
++static void devm_led_classdev_multicolor_release(struct device *dev, void *res)
++{
++ led_classdev_multicolor_unregister(*(struct led_classdev_mc **)res);
++}
++
++int devm_led_classdev_multicolor_register_ext(struct device *parent,
++ struct led_classdev_mc *mcled_cdev,
++ struct led_init_data *init_data)
++{
++ struct led_classdev_mc **dr;
++ int ret;
++
++ dr = devres_alloc(devm_led_classdev_multicolor_release,
++ sizeof(*dr), GFP_KERNEL);
++ if (!dr)
++ return -ENOMEM;
++
++ ret = led_classdev_multicolor_register_ext(parent, mcled_cdev,
++ init_data);
++ if (ret) {
++ devres_free(dr);
++ return ret;
++ }
++
++ *dr = mcled_cdev;
++ devres_add(parent, dr);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(devm_led_classdev_multicolor_register_ext);
++
++static int devm_led_classdev_multicolor_match(struct device *dev,
++ void *res, void *data)
++{
++ struct led_classdev_mc **p = res;
++
++ if (WARN_ON(!p || !*p))
++ return 0;
++
++ return *p == data;
++}
++
++void devm_led_classdev_multicolor_unregister(struct device *dev,
++ struct led_classdev_mc *mcled_cdev)
++{
++ WARN_ON(devres_release(dev,
++ devm_led_classdev_multicolor_release,
++ devm_led_classdev_multicolor_match, mcled_cdev));
++}
++EXPORT_SYMBOL_GPL(devm_led_classdev_multicolor_unregister);
++
++MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
++MODULE_DESCRIPTION("Multicolor LED class interface");
++MODULE_LICENSE("GPL v2");
+diff --git a/drivers/leds/leds-pwm-multicolor.c b/drivers/leds/leds-pwm-multicolor.c
+new file mode 100644
+index 0000000..e1e2daa
+--- /dev/null
++++ b/drivers/leds/leds-pwm-multicolor.c
+@@ -0,0 +1,194 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * PWM-based multi-color LED control
++ *
++ * Copyright 2022 Sven Schwermer <sven.schwermer@disruptive-technologies.com>
++ */
++
++#include <linux/err.h>
++#include <linux/kernel.h>
++#include <linux/led-class-multicolor.h>
++#include <linux/leds.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/platform_device.h>
++#include <linux/property.h>
++#include <linux/pwm.h>
++
++struct pwm_led {
++ struct pwm_device *pwm;
++ struct pwm_state state;
++ bool active_low;
++};
++
++struct pwm_mc_led {
++ struct led_classdev_mc mc_cdev;
++ struct mutex lock;
++ struct pwm_led leds[];
++};
++
++static int led_pwm_mc_set(struct led_classdev *cdev,
++ enum led_brightness brightness)
++{
++ struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev);
++ struct pwm_mc_led *priv = container_of(mc_cdev, struct pwm_mc_led, mc_cdev);
++ unsigned long long duty;
++ int ret = 0;
++ int i;
++
++ led_mc_calc_color_components(mc_cdev, brightness);
++
++ mutex_lock(&priv->lock);
++
++ for (i = 0; i < mc_cdev->num_colors; i++) {
++ duty = priv->leds[i].state.period;
++ duty *= mc_cdev->subled_info[i].brightness;
++ do_div(duty, cdev->max_brightness);
++
++ if (priv->leds[i].active_low)
++ duty = priv->leds[i].state.period - duty;
++
++ priv->leds[i].state.duty_cycle = duty;
++ priv->leds[i].state.enabled = duty > 0;
++ ret = pwm_apply_state(priv->leds[i].pwm,
++ &priv->leds[i].state);
++ if (ret)
++ break;
++ }
++
++ mutex_unlock(&priv->lock);
++
++ return ret;
++}
++
++static int iterate_subleds(struct device *dev, struct pwm_mc_led *priv,
++ struct fwnode_handle *mcnode)
++{
++ struct mc_subled *subled = priv->mc_cdev.subled_info;
++ struct fwnode_handle *fwnode;
++ struct pwm_led *pwmled;
++ u32 color;
++ int ret;
++
++ /* iterate over the nodes inside the multi-led node */
++ fwnode_for_each_child_node(mcnode, fwnode) {
++ pwmled = &priv->leds[priv->mc_cdev.num_colors];
++ pwmled->pwm = devm_fwnode_pwm_get(dev, fwnode, NULL);
++ if (IS_ERR(pwmled->pwm)) {
++ ret = PTR_ERR(pwmled->pwm);
++ dev_err(dev, "unable to request PWM: %d\n", ret);
++ goto release_fwnode;
++ }
++ pwm_init_state(pwmled->pwm, &pwmled->state);
++ pwmled->active_low = fwnode_property_read_bool(fwnode, "active-low");
++
++ ret = fwnode_property_read_u32(fwnode, "color", &color);
++ if (ret) {
++ dev_err(dev, "cannot read color: %d\n", ret);
++ goto release_fwnode;
++ }
++
++ subled[priv->mc_cdev.num_colors].color_index = color;
++ priv->mc_cdev.num_colors++;
++ }
++
++ return 0;
++
++release_fwnode:
++ fwnode_handle_put(fwnode);
++ return ret;
++}
++
++static int led_pwm_mc_probe(struct platform_device *pdev)
++{
++ struct fwnode_handle *mcnode, *fwnode;
++ struct led_init_data init_data = {};
++ struct led_classdev *cdev;
++ struct mc_subled *subled;
++ struct pwm_mc_led *priv;
++ int count = 0;
++ int ret = 0;
++
++ mcnode = device_get_named_child_node(&pdev->dev, "multi-led");
++ if (!mcnode) {
++ ret = -ENODEV;
++ dev_err(&pdev->dev, "expected multi-led node\n");
++ return ret;
++ }
++
++ /* count the nodes inside the multi-led node */
++ fwnode_for_each_child_node(mcnode, fwnode)
++ count++;
++
++ priv = devm_kzalloc(&pdev->dev, struct_size(priv, leds, count),
++ GFP_KERNEL);
++ if (!priv) {
++ ret = -ENOMEM;
++ goto release_mcnode;
++ }
++ mutex_init(&priv->lock);
++
++ subled = devm_kcalloc(&pdev->dev, count, sizeof(*subled), GFP_KERNEL);
++ if (!subled) {
++ ret = -ENOMEM;
++ goto release_mcnode;
++ }
++ priv->mc_cdev.subled_info = subled;
++
++ /* init the multicolor's LED class device */
++ cdev = &priv->mc_cdev.led_cdev;
++ fwnode_property_read_u32(mcnode, "max-brightness",
++ &cdev->max_brightness);
++ cdev->flags = LED_CORE_SUSPENDRESUME;
++ cdev->brightness_set_blocking = led_pwm_mc_set;
++
++ ret = iterate_subleds(&pdev->dev, priv, mcnode);
++ if (ret)
++ goto release_mcnode;
++
++ init_data.fwnode = mcnode;
++ ret = devm_led_classdev_multicolor_register_ext(&pdev->dev,
++ &priv->mc_cdev,
++ &init_data);
++ if (ret) {
++ dev_err(&pdev->dev,
++ "failed to register multicolor PWM led for %s: %d\n",
++ cdev->name, ret);
++ goto release_mcnode;
++ }
++
++ ret = led_pwm_mc_set(cdev, cdev->brightness);
++ if (ret) {
++ dev_err(&pdev->dev,
++ "failed to set led PWM value for %s\n", cdev->name);
++ return ret;
++ }
++
++ platform_set_drvdata(pdev, priv);
++ return 0;
++
++release_mcnode:
++ fwnode_handle_put(mcnode);
++ return ret;
++}
++
++static const struct of_device_id of_pwm_leds_mc_match[] = {
++ { .compatible = "pwm-leds-multicolor", },
++ {}
++};
++MODULE_DEVICE_TABLE(of, of_pwm_leds_mc_match);
++
++static struct platform_driver led_pwm_mc_driver = {
++ .probe = led_pwm_mc_probe,
++ .driver = {
++ .name = "leds_pwm_multicolor",
++ .of_match_table = of_pwm_leds_mc_match,
++ },
++};
++module_platform_driver(led_pwm_mc_driver);
++
++MODULE_AUTHOR("Sven Schwermer <sven.schwermer@disruptive-technologies.com>");
++MODULE_DESCRIPTION("multi-color PWM LED driver");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:leds-pwm-multicolor");
+diff --git a/include/linux/led-class-multicolor.h b/include/linux/led-class-multicolor.h
+new file mode 100644
+index 0000000..210d57b
+--- /dev/null
++++ b/include/linux/led-class-multicolor.h
+@@ -0,0 +1,109 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/* LED Multicolor class interface
++ * Copyright (C) 2019-20 Texas Instruments Incorporated - http://www.ti.com/
++ */
++
++#ifndef _LINUX_MULTICOLOR_LEDS_H_INCLUDED
++#define _LINUX_MULTICOLOR_LEDS_H_INCLUDED
++
++#include <linux/leds.h>
++#include <dt-bindings/leds/common.h>
++
++struct mc_subled {
++ unsigned int color_index;
++ unsigned int brightness;
++ unsigned int intensity;
++ unsigned int channel;
++};
++
++struct led_classdev_mc {
++ /* led class device */
++ struct led_classdev led_cdev;
++ unsigned int num_colors;
++
++ struct mc_subled *subled_info;
++};
++
++static inline struct led_classdev_mc *lcdev_to_mccdev(
++ struct led_classdev *led_cdev)
++{
++ return container_of(led_cdev, struct led_classdev_mc, led_cdev);
++}
++
++#if IS_ENABLED(CONFIG_LEDS_CLASS_MULTICOLOR)
++/**
++ * led_classdev_multicolor_register_ext - register a new object of led_classdev
++ * class with support for multicolor LEDs
++ * @parent: the multicolor LED to register
++ * @mcled_cdev: the led_classdev_mc structure for this device
++ * @init_data: the LED class multicolor device initialization data
++ *
++ * Returns: 0 on success or negative error value on failure
++ */
++int led_classdev_multicolor_register_ext(struct device *parent,
++ struct led_classdev_mc *mcled_cdev,
++ struct led_init_data *init_data);
++
++/**
++ * led_classdev_multicolor_unregister - unregisters an object of led_classdev
++ * class with support for multicolor LEDs
++ * @mcled_cdev: the multicolor LED to unregister
++ *
++ * Unregister a previously registered via led_classdev_multicolor_register
++ * object
++ */
++void led_classdev_multicolor_unregister(struct led_classdev_mc *mcled_cdev);
++
++/* Calculate brightness for the monochrome LED cluster */
++int led_mc_calc_color_components(struct led_classdev_mc *mcled_cdev,
++ enum led_brightness brightness);
++
++int devm_led_classdev_multicolor_register_ext(struct device *parent,
++ struct led_classdev_mc *mcled_cdev,
++ struct led_init_data *init_data);
++
++void devm_led_classdev_multicolor_unregister(struct device *parent,
++ struct led_classdev_mc *mcled_cdev);
++#else
++
++static inline int led_classdev_multicolor_register_ext(struct device *parent,
++ struct led_classdev_mc *mcled_cdev,
++ struct led_init_data *init_data)
++{
++ return 0;
++}
++
++static inline void led_classdev_multicolor_unregister(struct led_classdev_mc *mcled_cdev) {};
++static inline int led_mc_calc_color_components(struct led_classdev_mc *mcled_cdev,
++ enum led_brightness brightness)
++{
++ return 0;
++}
++
++static inline int devm_led_classdev_multicolor_register_ext(struct device *parent,
++ struct led_classdev_mc *mcled_cdev,
++ struct led_init_data *init_data)
++{
++ return 0;
++}
++
++static inline void devm_led_classdev_multicolor_unregister(struct device *parent,
++ struct led_classdev_mc *mcled_cdev)
++{};
++
++#endif /* IS_ENABLED(CONFIG_LEDS_CLASS_MULTICOLOR) */
++
++static inline int led_classdev_multicolor_register(struct device *parent,
++ struct led_classdev_mc *mcled_cdev)
++{
++ return led_classdev_multicolor_register_ext(parent, mcled_cdev, NULL);
++}
++
++static inline int devm_led_classdev_multicolor_register(struct device *parent,
++ struct led_classdev_mc *mcled_cdev)
++{
++ return devm_led_classdev_multicolor_register_ext(parent, mcled_cdev,
++ NULL);
++}
++
++#endif /* _LINUX_MULTICOLOR_LEDS_H_INCLUDED */
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-1900-lib-add-Dhrystone-benchmark-test.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1900-v6.3-lib-add-Dhrystone-benchmark-test.patch
similarity index 100%
rename from recipes-kernel/linux/linux-mediatek-5.4/generic/backport-5.4/999-1900-lib-add-Dhrystone-benchmark-test.patch
rename to recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-1900-v6.3-lib-add-Dhrystone-benchmark-test.patch
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2152-sound-add-mt7986-driver.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2152-sound-add-mt7986-driver.patch
deleted file mode 100644
index 41eb05e..0000000
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2152-sound-add-mt7986-driver.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From 593cfdef7ef160c49db5c7ae315cb963f32a947a Mon Sep 17 00:00:00 2001
-From: Sam Shih <sam.shih@mediatek.com>
-Date: Fri, 2 Jun 2023 13:06:08 +0800
-Subject: [PATCH] [slow-speed-io][999-2152-sound-add-mt7986-driver.patch]
-
----
- sound/soc/mediatek/Kconfig | 30 ++++++++++++++++++++++++++++++
- sound/soc/mediatek/Makefile | 1 +
- 2 files changed, 31 insertions(+)
-
-diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
-index 111e44b64..25e392428 100644
---- a/sound/soc/mediatek/Kconfig
-+++ b/sound/soc/mediatek/Kconfig
-@@ -53,6 +53,36 @@ config SND_SOC_MT6797_MT6351
- Select Y if you have such device.
- If unsure select "N".
-
-+config SND_SOC_MT79XX
-+ tristate "ASoC support for Mediatek MT79XX chip"
-+ depends on ARCH_MEDIATEK
-+ select SND_SOC_MEDIATEK
-+ help
-+ This adds ASoC platform driver support for Mediatek MT79XX chip
-+ that can be used with other codecs.
-+ Select Y if you have such device.
-+ If unsure select "N".
-+
-+config SND_SOC_MT79XX_WM8960
-+ tristate "ASoc Audio driver for MT79XX with WM8960 codec"
-+ depends on SND_SOC_MT79XX && I2C
-+ select SND_SOC_WM8960
-+ help
-+ This adds ASoC driver for Mediatek MT79XX boards
-+ with the WM8960 codecs.
-+ Select Y if you have such device.
-+ If unsure select "N".
-+
-+config SND_SOC_MT79XX_SI3218X
-+ tristate "ASoc Audio driver for MT79XX with SI3218X codec"
-+ depends on SND_SOC_MT79XX && SPI
-+ select SND_SOC_SI3218X_SPI
-+ help
-+ This adds ASoC driver for Mediatek MT79XX boards
-+ with the SI3218X 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
-diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile
-index 76032cae6..9690326b2 100644
---- a/sound/soc/mediatek/Makefile
-+++ b/sound/soc/mediatek/Makefile
-@@ -2,5 +2,6 @@
- obj-$(CONFIG_SND_SOC_MEDIATEK) += common/
- obj-$(CONFIG_SND_SOC_MT2701) += mt2701/
- obj-$(CONFIG_SND_SOC_MT6797) += mt6797/
-+obj-$(CONFIG_SND_SOC_MT79XX) += mt79xx/
- obj-$(CONFIG_SND_SOC_MT8173) += mt8173/
- obj-$(CONFIG_SND_SOC_MT8183) += mt8183/
---
-2.34.1
-
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2152-sound-add-mt7986-si3218x-driver.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2152-sound-add-mt7986-si3218x-driver.patch
new file mode 100644
index 0000000..b05b709
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2152-sound-add-mt7986-si3218x-driver.patch
@@ -0,0 +1,43 @@
+From f0f7fed920e63ce231c4ded63098a3abdf4b5b28 Mon Sep 17 00:00:00 2001
+From: Maso Huang <maso.huang@mediatek.com>
+Date: Thu, 16 Nov 2023 15:11:30 +0800
+Subject: [PATCH] sound add mt7986 si3218x driver
+
+---
+ sound/soc/mediatek/Kconfig | 10 ++++++++++
+ sound/soc/mediatek/mt7986/Makefile | 1 +
+ 2 files changed, 11 insertions(+)
+
+diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
+index 99d36c4..e28b5a6 100644
+--- a/sound/soc/mediatek/Kconfig
++++ b/sound/soc/mediatek/Kconfig
+@@ -73,6 +73,16 @@ config SND_SOC_MT7986_WM8960
+ Select Y if you have such device.
+ If unsure select "N".
+
++config SND_SOC_MT7986_SI3218X
++ tristate "ASoc Audio driver for MT7986 with SI3218X codec"
++ depends on SND_SOC_MT7986 && SPI
++ select SND_SOC_SI3218X_SPI
++ help
++ This adds support for ASoC machine driver for MediaTek MT7986
++ boards with the SI3218X 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
+diff --git a/sound/soc/mediatek/mt7986/Makefile b/sound/soc/mediatek/mt7986/Makefile
+index fc4c825..22d2571 100644
+--- a/sound/soc/mediatek/mt7986/Makefile
++++ b/sound/soc/mediatek/mt7986/Makefile
+@@ -7,3 +7,4 @@ snd-soc-mt7986-afe-objs := \
+
+ obj-$(CONFIG_SND_SOC_MT7986) += snd-soc-mt7986-afe.o
+ obj-$(CONFIG_SND_SOC_MT7986_WM8960) += mt7986-wm8960.o
++obj-$(CONFIG_SND_SOC_MT7986_SI3218X) += mt7986-si3218x.o
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2153-sound-add-si3218x-spi-driver.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2153-sound-add-si3218x-spi-driver.patch
new file mode 100644
index 0000000..f6d8795
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2153-sound-add-si3218x-spi-driver.patch
@@ -0,0 +1,60 @@
+From f1ebe890b6076434fbe71890ebc10a64fa2edd57 Mon Sep 17 00:00:00 2001
+From: Maso Huang <maso.huang@mediatek.com>
+Date: Wed, 15 Nov 2023 13:37:38 +0800
+Subject: [PATCH] sound add si3218x spi driver
+
+---
+ sound/soc/codecs/Kconfig | 9 +++++++++
+ sound/soc/codecs/Makefile | 5 +++++
+ 2 files changed, 14 insertions(+)
+
+diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
+index dfc536c..b5a7b2a 100644
+--- a/sound/soc/codecs/Kconfig
++++ b/sound/soc/codecs/Kconfig
+@@ -127,6 +127,7 @@ config SND_SOC_ALL_CODECS
+ select SND_SOC_NAU8822 if I2C
+ select SND_SOC_NAU8824 if I2C
+ select SND_SOC_NAU8825 if I2C
++ select SND_SOC_SI3218X_SPI
+ select SND_SOC_HDMI_CODEC
+ select SND_SOC_PCM1681 if I2C
+ select SND_SOC_PCM1789_I2C if I2C
+@@ -1488,6 +1489,14 @@ config SND_SOC_NAU8824
+ config SND_SOC_NAU8825
+ tristate
+
++#config SND_SOC_SI3218X
++# tristate
++
++config SND_SOC_SI3218X_SPI
++ tristate "Proslic SI3218X CODEC - SPI"
++ depends on SPI
++# select SND_SOC_SI3218X
++
+ config SND_SOC_TPA6130A2
+ tristate "Texas Instruments TPA6130A2 headphone amplifier"
+ depends on I2C
+diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
+index c498373..dbd437e 100644
+--- a/sound/soc/codecs/Makefile
++++ b/sound/soc/codecs/Makefile
+@@ -176,6 +176,7 @@ snd-soc-alc5632-objs := alc5632.o
+ snd-soc-sigmadsp-objs := sigmadsp.o
+ snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o
+ snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o
++snd-soc-si3218x-spi-objs := si3218x-spi.o
+ snd-soc-si476x-objs := si476x.o
+ snd-soc-sirf-audio-codec-objs := sirf-audio-codec.o
+ snd-soc-spdif-tx-objs := spdif_transmitter.o
+@@ -563,3 +564,7 @@ obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
+ obj-$(CONFIG_SND_SOC_MAX98504) += snd-soc-max98504.o
+ obj-$(CONFIG_SND_SOC_SIMPLE_AMPLIFIER) += snd-soc-simple-amplifier.o
+ obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
++
++# Proslic si3218x
++#obj-$(CONFIG_SND_SOC_SI3218X) += si3218x/
++obj-$(CONFIG_SND_SOC_SI3218X_SPI) += snd-soc-si3218x-spi.o
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2850-fips-140-3-compliance.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2850-fips-140-3-compliance.patch
new file mode 100644
index 0000000..41f2da4
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/999-2850-fips-140-3-compliance.patch
@@ -0,0 +1,69 @@
+--- a/crypto/Kconfig
++++ b/crypto/Kconfig
+@@ -1823,6 +1823,19 @@ config CRYPTO_JITTERENTROPY
+ random numbers. This Jitterentropy RNG registers with
+ the kernel crypto API and can be used by any caller.
+
++config CRYPTO_CPU_JITTERENTROPY_DEBUG
++ bool "Jitterentropy DEBUG FS"
++ default n
++ select CRYPTO_USER
++ select CRYPTO_JITTERENTROPY
++ select CRYPTO_USER_API_RNG
++ help
++ Enable the DebugFS interface of the CPU Jitter
++ random number generator. It is solely intended
++ to aid testing and for performing statistical
++ and entropy analyses. You should say no
++ unless you know what you are doing.
++
+ config CRYPTO_USER_API
+ tristate
+
+@@ -1853,6 +1868,17 @@ config CRYPTO_USER_API_RNG
+ This option enables the user-spaces interface for random
+ number generator algorithms.
+
++config CRYPTO_USER_API_RNG_CAVP
++ bool "Enable CAVP testing of DRBG"
++ select CRYPTO_USER_API_HASH
++ select CRYPTO_DRBG
++ default n
++ help
++ This option enables extra API for CAVP testing via the user-space
++ interface: resetting of DRBG entropy, and providing Additional Data.
++ This should only be enabled for CAVP testing. You should say
++ no unless you know what this is.
++
+ config CRYPTO_USER_API_AEAD
+ tristate "User-space interface for AEAD cipher algorithms"
+ depends on NET
+@@ -1879,6 +1904,16 @@ config CRYPTO_STATS
+ config CRYPTO_HASH_INFO
+ bool
+
++config CRYPTO_CAVP_TEST
++ bool "Enable CAVP testing of DRBG and JITTERRNG"
++ select CRYPTO_DRBG
++ select CRYPTO_DRBG_MENU
++ select CRYPTO_CPU_JITTERENTROPY_DEBUG
++ select CRYPTO_USER_API_RNG_CAVP
++ default n
++ help
++ This option enables DRBG CAVP test and JITTERENG CMVP test
++
+ source "lib/crypto/Kconfig"
+ source "drivers/crypto/Kconfig"
+ source "crypto/asymmetric_keys/Kconfig"
+
+--- a/crypto/algif_rng.c
++++ b/crypto/algif_rng.c
+@@ -51,7 +51,7 @@ MODULE_AUTHOR("Stephan Mueller <smueller
+ MODULE_DESCRIPTION("User-space interface for random number generators");
+
+ struct rng_ctx {
+-#define MAXSIZE 128
++#define MAXSIZE 256
+ unsigned int len;
+ struct crypto_rng *drng;
+ u8 *addtl;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
index af8b569..e927bc3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/patches-5.4.inc
@@ -35,10 +35,9 @@
file://1010-pcie-mediatek-fix-clearing-interrupt-status.patch \
file://1020-spi-nor-w25q512jv.patch \
file://1021-ubnt-ledbar-driver.patch \
- file://999-1000-backport-pinctrl-pinconf-setting-combo.patch \
- file://999-1033-backport-pinctrl-spinlock.patch \
+ file://999-1050-v6.4-backport-jitterrng-2.2.0.patch \
+ file://999-1051-v5.10-backport-libkcapi.patch \
file://999-1600-mdiobus-add-c45.patch \
- file://999-1700-macsec-revert-async-support.patch \
file://999-1701-add-default-setting-to-dsa-unused-port.patch \
file://999-1702-net-dsa-add-MT7531-Gigabit-Ethernet-PHY-setting.patch \
file://999-1703-mxl-gpy-phy-support.patch \
@@ -51,6 +50,14 @@
file://999-1710-net-phy-add-phylink-pcs-support.patch;apply=no \
file://999-1711-net-phy-add-phylink-pcs-decode-helper.patch \
file://999-1712-net-phy-add-phylink-rate-matching-support.patch;apply=no \
+ file://999-1713-v5.15-net-dsa-add-dsa_port_from_netdev.patch \
+ file://999-1714-v5.15-net-dsa-add-netdev_upper_dev_link.patch \
+ file://999-1800-v6.7-MT7986-ASoC-platform-driver.patch \
+ file://999-1801-v6.1-iio-adc-add-rtq6056-support.patch \
+ file://999-1802-v6.4-backport-pinctrl-pinconf-setting-combo.patch \
+ file://999-1803-v6.6-pinctrl-spinlock.patch \
+ file://999-1804-v6.4-leds-pwm-multicolor.patch \
+ file://999-1900-v6.3-lib-add-Dhrystone-benchmark-test.patch \
file://999-2000-show_model_name_in_cpuinfo_on_arm64.patch \
file://999-2001-kgdb-add-interrupt-control.patch \
file://999-2010-clk-mtk-add-mt7986-support.patch \
@@ -77,7 +84,8 @@
file://999-2140-mtk-thermal-add-lvts-support.patch \
file://999-2150-sound-add-some-helpers-to-control-mtk_memif.patch \
file://999-2151-sound-refine-hw-params-and-hw-prepare.patch \
- file://999-2152-sound-add-mt7986-driver.patch \
+ file://999-2152-sound-add-mt7986-si3218x-driver.patch \
+ file://999-2153-sound-add-si3218x-spi-driver.patch \
file://999-2300-mtk-sd-add-mt7986-support.patch \
file://999-2301-mtk-sd-Add-subsys-clock-control.patch \
file://999-2330-mtd-spinand-winbond-Support-for-W25MxxGV-W25NxxKV-series.patch \
@@ -152,6 +160,7 @@
file://999-2729-net-phy-remove-reporting-line-rate-to-mac.patch;apply=no \
file://999-2730-net-phy-sfp-change-shared-mod-def0.patch \
file://999-2800-misc-add-mtk-platform.patch \
+ file://999-2850-fips-140-3-compliance.patch \
file://999-2900-dts-mt7622-enable-new-mtk-snand-for-ubi.patch \
file://999-2901-dts-mt7622-remove-cooling-device.patch \
"
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
new file mode 100644
index 0000000..2d4bfaa
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K.patch
@@ -0,0 +1,222 @@
+From 4136e3567f6904259babbe5ae5c0d0bf06413f57 Mon Sep 17 00:00:00 2001
+From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
+Date: Wed, 25 Oct 2023 09:21:06 +0800
+Subject: [PATCH] 999-2952-net-ethernet-mtk_eth_soc-modify-fq-size-4K
+
+---
+ drivers/net/ethernet/mediatek/mtk_eth_dbg.c | 2 +-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 74 ++++++++++---------
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 5 +-
+ .../ethernet/mediatek/mtk_hnat/hnat_debugfs.c | 2 +-
+ .../ethernet/mediatek/mtk_hnat/hnat_nf_hook.c | 23 ++++++
+ 5 files changed, 69 insertions(+), 37 deletions(-)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
+index e50e1ac..7c137e5 100755
+--- a/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_dbg.c
+@@ -882,7 +882,7 @@ int hwtx_ring_read(struct seq_file *seq, void *v)
+ struct mtk_tx_dma_v2 *hwtx_ring;
+ int i = 0;
+
+- for (i = 0; i < MTK_DMA_SIZE; i++) {
++ for (i = 0; i < MTK_DMA_FQ_SIZE; i++) {
+ dma_addr_t addr = eth->phy_scratch_ring +
+ i * (dma_addr_t)eth->soc->txrx.txd_size;
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+index 1226dd6..fe9c1de 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -1557,10 +1557,10 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
+ {
+ const struct mtk_soc_data *soc = eth->soc;
+ dma_addr_t phy_ring_tail;
+- int cnt = MTK_DMA_SIZE;
++ int cnt = MTK_DMA_FQ_SIZE;
+ dma_addr_t dma_addr;
+ u64 addr64 = 0;
+- int i;
++ int i, j, len;
+
+ if (!eth->soc->has_sram) {
+ eth->scratch_ring = dma_alloc_coherent(eth->dma_dev,
+@@ -1577,40 +1577,44 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
+ if (unlikely(!eth->scratch_ring))
+ return -ENOMEM;
+
+- eth->scratch_head = kcalloc(cnt, MTK_QDMA_PAGE_SIZE, GFP_KERNEL);
+- if (unlikely(!eth->scratch_head))
+- return -ENOMEM;
+-
+- dma_addr = dma_map_single(eth->dma_dev,
+- eth->scratch_head, cnt * MTK_QDMA_PAGE_SIZE,
+- DMA_FROM_DEVICE);
+- if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr)))
+- return -ENOMEM;
+-
+ phy_ring_tail = eth->phy_scratch_ring +
+ (dma_addr_t)soc->txrx.txd_size * (cnt - 1);
+
+- for (i = 0; i < cnt; i++) {
+- struct mtk_tx_dma_v2 *txd;
++ for (j = 0; j < DIV_ROUND_UP(MTK_DMA_FQ_SIZE, MTK_DMA_FQ_LENGTH); j++) {
++ len = min_t(int, cnt - j * MTK_DMA_FQ_LENGTH, MTK_DMA_FQ_LENGTH);
+
+- txd = eth->scratch_ring + i * soc->txrx.txd_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;
++ eth->scratch_head[j] = kcalloc(len, MTK_QDMA_PAGE_SIZE, GFP_KERNEL);
++ if (unlikely(!eth->scratch_head[j]))
++ return -ENOMEM;
+
+- addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
+- TX_DMA_SDP1(dma_addr + i * MTK_QDMA_PAGE_SIZE) : 0;
++ dma_addr = dma_map_single(eth->dma_dev,
++ eth->scratch_head[j], len * MTK_QDMA_PAGE_SIZE,
++ DMA_FROM_DEVICE);
++ if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr)))
++ return -ENOMEM;
+
+- txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE) | addr64;
+- txd->txd4 = 0;
++ for (i = 0; i < len; i++) {
++ struct mtk_tx_dma_v2 *txd;
+
+- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
+- MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+- txd->txd5 = 0;
+- txd->txd6 = 0;
+- txd->txd7 = 0;
+- txd->txd8 = 0;
++ txd = eth->scratch_ring + (j * MTK_DMA_FQ_LENGTH + i) * soc->txrx.txd_size;
++ txd->txd1 = dma_addr + i * MTK_QDMA_PAGE_SIZE;
++ if (j * MTK_DMA_FQ_LENGTH + i < cnt)
++ txd->txd2 = eth->phy_scratch_ring +
++ (j * MTK_DMA_FQ_LENGTH + i + 1) * soc->txrx.txd_size;
++
++ addr64 = (MTK_HAS_CAPS(eth->soc->caps, MTK_8GB_ADDRESSING)) ?
++ TX_DMA_SDP1(dma_addr + i * MTK_QDMA_PAGE_SIZE) : 0;
++
++ txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE) | addr64;
++ txd->txd4 = 0;
++
++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ||
++ MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
++ txd->txd5 = 0;
++ txd->txd6 = 0;
++ txd->txd7 = 0;
++ txd->txd8 = 0;
++ }
+ }
+ }
+
+@@ -2541,9 +2545,9 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
+ ring->dma = dma_alloc_coherent(eth->dma_dev, MTK_DMA_SIZE * sz,
+ &ring->phys, GFP_KERNEL);
+ else {
+- ring->dma = eth->scratch_ring + MTK_DMA_SIZE * sz;
++ ring->dma = eth->scratch_ring + MTK_DMA_FQ_SIZE * sz;
+ ring->phys = eth->phy_scratch_ring +
+- MTK_DMA_SIZE * (dma_addr_t)sz;
++ MTK_DMA_FQ_SIZE * (dma_addr_t)sz;
+ }
+
+ if (!ring->dma)
+@@ -3349,9 +3353,11 @@ static void mtk_dma_free(struct mtk_eth *eth)
+ mtk_rx_clean(eth, ð->rx_ring[MTK_RSS_RING(i)], 1);
+ }
+
+- if (eth->scratch_head) {
+- kfree(eth->scratch_head);
+- eth->scratch_head = NULL;
++ for (i = 0; i < DIV_ROUND_UP(MTK_DMA_FQ_SIZE, MTK_DMA_FQ_LENGTH); i++) {
++ if (eth->scratch_head[i]) {
++ kfree(eth->scratch_head[i]);
++ eth->scratch_head[i] = NULL;
++ }
+ }
+ }
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+index fe8bdee..cd2de23 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -20,6 +20,9 @@
+ #define MTK_MAX_RX_LENGTH 1536
+ #define MTK_MIN_TX_LENGTH 60
+ #define MTK_DMA_SIZE 2048
++#define MTK_DMA_FQ_SIZE 4096
++#define MTK_DMA_FQ_HEAD 32
++#define MTK_DMA_FQ_LENGTH 2048
+ #define MTK_NAPI_WEIGHT 256
+
+ #if defined(CONFIG_MEDIATEK_NETSYS_V3)
+@@ -1837,7 +1840,7 @@ struct mtk_eth {
+ void *scratch_ring;
+ struct mtk_reset_event reset_event;
+ dma_addr_t phy_scratch_ring;
+- void *scratch_head;
++ void *scratch_head[MTK_DMA_FQ_HEAD];
+ struct clk *clks[MTK_CLK_MAX];
+
+ struct mii_bus *mii_bus;
+diff --git a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
+index fc7d216..b97fd6a 100644
+--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
+@@ -2784,7 +2784,7 @@ static ssize_t hnat_qos_toggle_write(struct file *file, const char __user *buffe
+ qos_toggle = 1;
+ } else if (buf[0] == '2') {
+ pr_info("Per-port-per-queue mode is going to be enabled!\n");
+- pr_info("PPPQ use qid 0~5 (scheduler 0).\n");
++ pr_info("PPPQ use qid 0~11 (scheduler 0).\n");
+ qos_toggle = 2;
+ qos_dl_toggle = 1;
+ qos_ul_toggle = 1;
+diff --git a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+index 85c38e0..6a373f8 100644
+--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+@@ -1219,6 +1219,7 @@ static unsigned int skb_to_hnat_info(struct sk_buff *skb,
+ int udp = 0;
+ u32 qid = 0;
+ u32 port_id = 0;
++ u32 payload_len = 0;
+ int mape = 0;
+
+ ct = nf_ct_get(skb, &ctinfo);
+@@ -1748,6 +1749,28 @@ static unsigned int skb_to_hnat_info(struct sk_buff *skb,
+ else
+ qid = 0;
+
++ if (IS_PPPQ_MODE && IS_PPPQ_PATH(dev, skb)) {
++ if (ntohs(eth->h_proto) == ETH_P_IP) {
++ iph = ip_hdr(skb);
++ if (iph->protocol == IPPROTO_TCP) {
++ skb_set_transport_header(skb, sizeof(struct iphdr));
++ payload_len = be16_to_cpu(iph->tot_len) - skb_transport_offset(skb) - tcp_hdrlen(skb);
++ /* Dispatch ACK packets to high priority queue */
++ if (payload_len == 0)
++ qid += 6;
++ }
++ } else if (ntohs(eth->h_proto) == ETH_P_IPV6) {
++ ip6h = ipv6_hdr(skb);
++ if (ip6h->nexthdr == NEXTHDR_TCP) {
++ skb_set_transport_header(skb, sizeof(struct ipv6hdr));
++ payload_len = be16_to_cpu(ip6h->payload_len) - tcp_hdrlen(skb);
++ /* Dispatch ACK packets to high priority queue */
++ if (payload_len == 0)
++ qid += 6;
++ }
++ }
++ }
++
+ if (IS_IPV4_GRP(foe)) {
+ entry.ipv4_hnapt.iblk2.dp = gmac;
+ entry.ipv4_hnapt.iblk2.port_mg =
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3019-mtk-wed-add-wed3-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3019-mtk-wed-add-wed3-support.patch
index 1edbab9..7b27db3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3019-mtk-wed-add-wed3-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3019-mtk-wed-add-wed3-support.patch
@@ -1,4 +1,4 @@
-From b54ca484993804cec5941bd12c6cafc9ce51e4dc Mon Sep 17 00:00:00 2001
+From 7d891b389a58e3f8c99782339df7c0b023440558 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Mon, 18 Sep 2023 13:21:15 +0800
Subject: [PATCH] mtk:wed:add wed3 support
@@ -11,20 +11,20 @@
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 5 +-
drivers/net/ethernet/mediatek/mtk_ppe.c | 17 +-
drivers/net/ethernet/mediatek/mtk_ppe.h | 2 +-
- .../net/ethernet/mediatek/mtk_ppe_offload.c | 13 +-
+ .../net/ethernet/mediatek/mtk_ppe_offload.c | 16 +-
drivers/net/ethernet/mediatek/mtk_wed.c | 1178 +++++++++++++----
drivers/net/ethernet/mediatek/mtk_wed.h | 25 +-
.../net/ethernet/mediatek/mtk_wed_debugfs.c | 584 +++++++-
- drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 13 +-
+ drivers/net/ethernet/mediatek/mtk_wed_mcu.c | 14 +-
drivers/net/ethernet/mediatek/mtk_wed_mcu.h | 5 +-
drivers/net/ethernet/mediatek/mtk_wed_regs.h | 338 ++++-
include/linux/netdevice.h | 7 +
include/linux/soc/mediatek/mtk_wed.h | 83 +-
- 16 files changed, 2069 insertions(+), 388 deletions(-)
+ 16 files changed, 2070 insertions(+), 391 deletions(-)
mode change 100755 => 100644 drivers/net/ethernet/mediatek/mtk_ppe.c
diff --git a/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
-index 561450e..8995ea3 100644
+index bcfa581..c866d85 100644
--- a/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
@@ -205,44 +205,49 @@
@@ -214,7 +214,7 @@
};
reserved-memory {
-@@ -902,6 +939,7 @@
+@@ -906,6 +943,7 @@
<&topckgen CK_TOP_CB_SGM_325M>;
mediatek,ethsys = <ðsys>;
mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
@@ -283,10 +283,10 @@
+};
\ No newline at end of file
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-index 8bd526a..dea66d7 100644
+index 86ab1f1..ec5e5ec 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -5095,7 +5095,8 @@ static int mtk_probe(struct platform_device *pdev)
+@@ -5218,7 +5218,8 @@ static int mtk_probe(struct platform_device *pdev)
"mediatek,wed", i);
static const u32 wdma_regs[] = {
MTK_WDMA0_BASE,
@@ -297,10 +297,10 @@
void __iomem *wdma;
u32 wdma_phy;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-index ee89b4c..8656b5f 100644
+index 3ab8ab5..f10fed1 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
-@@ -613,9 +613,12 @@
+@@ -623,9 +623,12 @@
#define RX_DMA_SPORT_MASK 0x7
#define RX_DMA_SPORT_MASK_V2 0xf
@@ -317,7 +317,7 @@
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
old mode 100755
new mode 100644
-index 384e811..eda23c2
+index 0e9c0bd..ae0acd5
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -9,6 +9,7 @@
@@ -328,7 +328,7 @@
#include "mtk_eth_soc.h"
#include "mtk_ppe.h"
#include "mtk_ppe_regs.h"
-@@ -396,7 +397,7 @@ int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid)
+@@ -407,7 +408,7 @@ int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid)
}
int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
@@ -337,7 +337,7 @@
{
struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(entry);
u32 *ib2 = mtk_foe_entry_ib2(entry);
-@@ -408,6 +409,9 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
+@@ -419,6 +420,9 @@ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
l2->winfo = FIELD_PREP(MTK_FOE_WINFO_WCID, wcid) |
FIELD_PREP(MTK_FOE_WINFO_BSS, bss);
@@ -347,7 +347,7 @@
#else
if (wdma_idx)
*ib2 |= MTK_FOE_IB2_WDMA_DEVIDX;
-@@ -443,6 +447,17 @@ int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp)
+@@ -454,6 +458,17 @@ int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp)
*ib2 &= ~MTK_FOE_IB2_DSCP;
*ib2 |= FIELD_PREP(MTK_FOE_IB2_DSCP, dscp);
@@ -356,7 +356,7 @@
+
+ if (*ib2 & MTK_FOE_IB2_WDMA_WINFO &&
+ l2->winfo_pao & MTK_FOE_WINFO_PAO_AMSDU_EN) {
-+ u8 tid = rt_tos2priority(dscp) & 0xf;
++ u8 tid = (dscp >> 5) & 0xf;
+
+ l2->winfo_pao |= FIELD_PREP(MTK_FOE_WINFO_PAO_TID, tid);
+ }
@@ -379,7 +379,7 @@
int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp);
bool mtk_foe_entry_match(struct mtk_foe_entry *entry, struct mtk_foe_entry *data);
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
-index 95174b7..eab9e9d 100644
+index 95174b7..339359e 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
@@ -112,6 +112,7 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i
@@ -407,18 +407,28 @@
else
return -EOPNOTSUPP;
#endif
-@@ -490,8 +493,8 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+@@ -481,8 +484,6 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+ if (data.pppoe.num == 1)
+ mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid);
+
+- mtk_foe_entry_set_dscp(&foe, dscp);
+-
+ mtk_foe_entry_set_sp(eth->ppe[ppe_index], &foe);
+
+ err = mtk_flow_set_output_device(eth, &foe, odev, f->flow->ct, data.eth.h_dest,
+@@ -490,8 +491,9 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
if (err)
return err;
- if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0)
- return err;
++ mtk_foe_entry_set_dscp(&foe, dscp);
+ /*if (wed_index >= 0 && (err = mtk_wed_flow_add(wed_index)) < 0)
+ return err;*/
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
-@@ -516,8 +519,8 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+@@ -516,8 +518,8 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
mtk_foe_entry_clear(eth->ppe[ppe_index], entry);
free:
kfree(entry);
@@ -2941,7 +2951,7 @@
}
}
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
-index 96e30a3..055594d 100644
+index b5a86f6..c2d060b 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.c
@@ -245,8 +245,7 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
@@ -2954,7 +2964,7 @@
ret = request_firmware(&fw, mcu, wo->hw->dev);
if (ret)
-@@ -289,8 +289,12 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
+@@ -293,8 +292,12 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
}
/* write the start address */
@@ -2969,7 +2979,7 @@
wo_w32(wo, boot_cr, (wo->region[WO_REGION_EMI].addr_pa >> 16));
/* wo firmware reset */
-@@ -298,8 +302,7 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
+@@ -302,8 +305,7 @@ mtk_wed_load_firmware(struct mtk_wed_wo *wo)
val = wo_r32(wo, WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR);
@@ -2980,7 +2990,7 @@
wo_w32(wo, WOX_MCU_CFG_LS_WF_MCU_CFG_WM_WA_ADDR, val);
diff --git a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
-index 19e1199..c07bdb6 100644
+index dbb17ae..a533b6e 100644
--- a/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
+++ b/drivers/net/ethernet/mediatek/mtk_wed_mcu.h
@@ -17,8 +17,9 @@
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mediatek-ethernet-add-multiple-ppe-allocation.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mediatek-ethernet-add-multiple-ppe-allocation.patch
new file mode 100644
index 0000000..9ac533a
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3022-mediatek-ethernet-add-multiple-ppe-allocation.patch
@@ -0,0 +1,89 @@
+From 9c849a6e5a246489c5c91565d4c89a32958cad29 Mon Sep 17 00:00:00 2001
+From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
+Date: Thu, 16 Nov 2023 11:21:53 +0800
+Subject: [PATCH] 999-3022-mediatek-ethernet-add-multiple-ppe-allocation
+
+---
+ arch/arm64/boot/dts/mediatek/mt7988.dtsi | 1 +
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 10 +++++++++-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 ++
+ drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 10 ++++++++++
+ 4 files changed, 22 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+index 8d83f6b..d378a65 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7988.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+@@ -950,6 +950,7 @@
+ mediatek,infracfg = <&topmisc>;
+ mediatek,toprgu = <&watchdog>;
+ mediatek,hwver = <&hwver>;
++ mtketh-ppe-num = <3>;
+ #reset-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+index de2eac4..55d05fd 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -3669,7 +3669,14 @@ static int mtk_open(struct net_device *dev)
+ SGMSYS_QPHY_PWR_STATE_CTRL, 0);
+
+ if (eth->soc->offload_version) {
+- gdm_config = MTK_GDMA_TO_PPE0;
++#if defined(CONFIG_MEDIATEK_NETSYS_V2) || defined(CONFIG_MEDIATEK_NETSYS_V3)
++ if (eth->ppe_num >= 3 && mac->id == 2)
++ gdm_config = MTK_GDMA_TO_PPE2;
++ else if (eth->ppe_num >=2 && mac->id == 1)
++ gdm_config = MTK_GDMA_TO_PPE1;
++ else
++#endif
++ gdm_config = MTK_GDMA_TO_PPE0;
+
+ for (i = 0; i < eth->ppe_num; i++)
+ mtk_ppe_start(eth->ppe[i]);
+@@ -4635,6 +4642,7 @@ static const struct net_device_ops mtk_netdev_ops = {
+ .ndo_poll_controller = mtk_poll_controller,
+ #endif
+ .ndo_setup_tc = mtk_eth_setup_tc,
++ .ndo_fill_receive_path = mtk_eth_fill_receive_path,
+ };
+
+ static void mux_poll(struct work_struct *work)
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+index 50024a2..e0dfc9d 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -2041,6 +2041,8 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
+ void *type_data);
+ int mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f,
+ struct mtk_eth *eth);
++int mtk_eth_fill_receive_path(struct net_device_path_ctx *ctx,
++ struct net_device_path *path);
+ void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev);
+ u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index);
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+index eab9e9d..e5ff575 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+@@ -694,6 +694,16 @@ int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type,
+ }
+ }
+
++int mtk_eth_fill_receive_path(struct net_device_path_ctx *ctx,
++ struct net_device_path *path)
++{
++ struct mtk_mac *mac = netdev_priv(ctx->dev);
++
++ path->mtk_wdma.wdma_idx = mac->id;
++
++ return 0;
++}
++
+ int mtk_eth_offload_init(struct mtk_eth *eth, int id)
+ {
+ if (!eth->ppe[id] || !eth->ppe[id]->foe_table)
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3024-mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3024-mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ.patch
new file mode 100644
index 0000000..31d8b89
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/wed3/999-3024-mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ.patch
@@ -0,0 +1,57 @@
+From 8306aa4c52abf96af2c229762207369f279c89e2 Mon Sep 17 00:00:00 2001
+From: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
+Date: Tue, 28 Nov 2023 13:25:03 +0800
+Subject: [PATCH] 999-3024-mtk-ppe-dispatch-short-packets-to-high-priority-TXQ-in-PPPQ
+
+---
+ drivers/net/ethernet/mediatek/mtk_ppe.c | 27 +++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
+index 16aec2e..1e2b96e 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
+@@ -451,6 +451,28 @@ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid)
+ return 0;
+ }
+
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++void mtk_foe_entry_adjust_qid(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
++{
++ struct mtk_foe_mac_info *l2 = mtk_foe_entry_l2(&entry->data);
++ u32 *ib2 = mtk_foe_entry_ib2(&entry->data);
++ u8 qid;
++
++ if (l2->tport_id != 1)
++ return;
++
++ qid = FIELD_GET(MTK_FOE_IB2_QID, *ib2);
++ /* To enhance performance in the unbalanced PHY rate test,
++ * dispatching short packets to the high priority TXQ.
++ */
++ if (ppe->eth->qos_toggle == 2 && qid < 6) {
++ qid += 6;
++ *ib2 &= ~MTK_FOE_IB2_QID;
++ *ib2 |= FIELD_PREP(MTK_FOE_IB2_QID, qid);
++ }
++}
++#endif
++
+ int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp)
+ {
+ u32 *ib2 = mtk_foe_entry_ib2(entry);
+@@ -790,6 +812,11 @@ void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash)
+ continue;
+ }
+
++#if defined(CONFIG_MEDIATEK_NETSYS_V3)
++ if (skb && skb->len < 100)
++ mtk_foe_entry_adjust_qid(ppe, entry);
++#endif
++
+ entry->hash = hash;
+ __mtk_foe_entry_commit(ppe, &entry->data, hash);
+ found = true;
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek_5.4.bb b/recipes-kernel/linux/linux-mediatek_5.4.bb
index 6e4cf79..dde2f00 100644
--- a/recipes-kernel/linux/linux-mediatek_5.4.bb
+++ b/recipes-kernel/linux/linux-mediatek_5.4.bb
@@ -9,8 +9,8 @@
KBRANCH ?= "linux-5.4.y"
-LINUX_VERSION ?= "5.4.246"
-SRCREV_machine ?= "f568a20f058fa1e37069cff4aac4187c1650a0e9"
+LINUX_VERSION ?= "5.4.260"
+SRCREV_machine ?= "87e8e7a7aa1f96276252a90373de1d56add31918"
KMETA = "kernel-meta"
SRCREV_meta ?= "feeb59687bc0f054af837a5061f8d413ec7c93e9"