Merge "[rdk-b][common][bsp][Refactor and sync kernel/wifi from Openwrt]"
diff --git a/recipes-connectivity/atenl/files/src/eeprom.c b/recipes-connectivity/atenl/files/src/eeprom.c
index 1c1cb6c..d18262e 100644
--- a/recipes-connectivity/atenl/files/src/eeprom.c
+++ b/recipes-connectivity/atenl/files/src/eeprom.c
@@ -9,60 +9,38 @@
 #define EEPROM_PART_SIZE 0x64000
 char *eeprom_file;
 
-static FILE *mtd_open(const char *mtd)
+static int
+atenl_create_file(struct atenl *an, bool flash_mode)
 {
-	char line[128], name[64];
-	FILE *fp;
-	int i;
-
-	fp = fopen("/proc/mtd", "r");
-	if (!fp)
-		return NULL;
-
-	snprintf(name, sizeof(name), "\"%s\"", mtd);
-	while (fgets(line, sizeof(line), fp)) {
-		if (!sscanf(line, "mtd%d:", &i) || !strstr(line, name))
-			continue;
+	char fname[64], buf[1024];
+	ssize_t w, len, max_len, total_len = 0;
+	int fd_ori, fd, ret;
 
-		snprintf(line, sizeof(line), "/dev/mtd%d", i);
-		fclose(fp);
-		return fopen(line, "r");
+	/* reserve space for pre-cal data in flash mode */
+	if (flash_mode) {
+		atenl_dbg("%s: init eeprom with flash mode\n", __func__);
+		max_len = EEPROM_PART_SIZE;
+	} else {
+		atenl_dbg("%s: init eeprom with efuse mode\n", __func__);
+		max_len = 0x1000;
 	}
-	fclose(fp);
-
-	return NULL;
-}
 
-static int
-atenl_flash_create_file(struct atenl *an)
-{
-#define READ_LEN_LIMIT	0x64000
-	char buf[1024];
-	ssize_t len, limit = 0;
-	FILE *f;
-	int fd, ret;
-
-	f = mtd_open(an->mtd_part);
-	if (!f) {
-		atenl_err("Failed to open MTD device\n");
+	snprintf(fname, sizeof(fname),
+		 "/sys/kernel/debug/ieee80211/phy%d/mt76/eeprom",
+		 get_band_val(an, 0, phy_idx));
+	fd_ori = open(fname, O_RDONLY);
+	if (fd_ori < 0)
 		return -1;
-	}
-	fseek(f, an->mtd_offset, SEEK_SET);
 
 	fd = open(eeprom_file, O_RDWR | O_CREAT | O_EXCL, 00644);
 	if (fd < 0)
 		goto out;
 
-	while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
-		ssize_t w;
-
+	while ((len = read(fd_ori, buf, sizeof(buf))) > 0) {
 retry:
 		w = write(fd, buf, len);
 		if (w > 0) {
-			limit += len;
-
-			if (limit >= READ_LEN_LIMIT)
-				break;
+			total_len += len;
 			continue;
 		}
 
@@ -76,53 +54,27 @@
 		goto out;
 	}
 
-	ret = lseek(fd, 0, SEEK_SET);
-	if (ret) {
-		fclose(f);
-		close(fd);
-		return ret;
-	}
-
-out:
-	fclose(f);
-	return fd;
-}
-
-static int
-atenl_efuse_create_file(struct atenl *an)
-{
-	char fname[64], buf[1024];
-	ssize_t len;
-	int fd_ori, fd, ret;
-
-	snprintf(fname, sizeof(fname),
-		"/sys/kernel/debug/ieee80211/phy%d/mt76/eeprom", get_band_val(an, 0, phy_idx));
-	fd_ori = open(fname, O_RDONLY);
-	if (fd_ori < 0)
-		return -1;
-
-	fd = open(eeprom_file, O_RDWR | O_CREAT | O_EXCL, 00644);
-	if (fd < 0)
-		goto out;
-
-	while ((len = read(fd_ori, buf, sizeof(buf))) > 0) {
-		ssize_t w;
-
-retry:
+	/* reserve space for pre-cal data in flash mode */
+	len = sizeof(buf);
+	memset(buf, 0, len);
+	while (total_len < max_len) {
 		w = write(fd, buf, len);
-		if (w > 0)
-			continue;
 
-		if (errno == EINTR)
-			goto retry;
+		if (w > 0) {
+			total_len += len;
+			continue;
+		}
 
-		perror("write");
-		unlink(eeprom_file);
-		close(fd);
-		fd = -1;
-		goto out;
+		if (errno != EINTR) {
+			perror("write");
+			unlink(eeprom_file);
+			close(fd);
+			fd = -1;
+			goto out;
+		}
 	}
 
+
 	ret = lseek(fd, 0, SEEK_SET);
 	if (ret) {
 		close(fd_ori);
@@ -148,17 +100,8 @@
 {
 	int fd;
 
-	if (!atenl_eeprom_file_exists()) {
-		if (flash_mode)
-			atenl_dbg("%s: init eeprom with flash mode\n", __func__);
-		else
-			atenl_dbg("%s: init eeprom with efuse mode\n", __func__);
-
-		if (flash_mode)
-			return atenl_flash_create_file(an);
-
-		return atenl_efuse_create_file(an);
-	}
+	if (!atenl_eeprom_file_exists())
+		return atenl_create_file(an, flash_mode);
 
 	fd = open(eeprom_file, O_RDWR);
 	if (fd < 0)
diff --git a/recipes-connectivity/libnl-tiny/libnl-tiny_git.bb b/recipes-connectivity/libnl-tiny/libnl-tiny_git.bb
index d0ba98a..d751483 100644
--- a/recipes-connectivity/libnl-tiny/libnl-tiny_git.bb
+++ b/recipes-connectivity/libnl-tiny/libnl-tiny_git.bb
@@ -5,7 +5,7 @@
 SECTION = "libs"
 
 SRC_URI = "git://git.openwrt.org/project/libnl-tiny.git"
-SRCREV = "28c44ca97cd546ef8168e7476472a0da022b3421"
+SRCREV = "db3b2cdbca5277723326a2720024a59fb821ae36"
 PV = "git${SRCPV}"
 
 inherit cmake pkgconfig
diff --git a/recipes-connectivity/linux-mac80211/linux-mac80211.bb b/recipes-connectivity/linux-mac80211/linux-mac80211.bb
index 7c348fe..93c478b 100644
--- a/recipes-connectivity/linux-mac80211/linux-mac80211.bb
+++ b/recipes-connectivity/linux-mac80211/linux-mac80211.bb
@@ -64,12 +64,6 @@
 do_install_append() {
     # Module
     cat ${D}/usr/include/linux-mac80211/Module.symvers >> ${TMPDIR}/work-shared/${MACHINE}/kernel-build-artifacts/Module.symvers
-    install -d ${D}/lib/modules/${KERNEL_VERSION}/updates/compat/
-    install -d ${D}/lib/modules/${KERNEL_VERSION}/updates/net/wireless
-    install -d ${D}/lib/modules/${KERNEL_VERSION}/updates/net/mac80211
-    install -m 0644 ${B}/compat/compat.ko ${D}/lib/modules/${KERNEL_VERSION}/updates/compat/
-    install -m 0644 ${B}/net/wireless/cfg80211.ko ${D}/lib/modules/${KERNEL_VERSION}/updates/net/wireless/
-    install -m 0644 ${B}/net/mac80211/mac80211.ko ${D}/lib/modules/${KERNEL_VERSION}/updates/net/mac80211/
 }
 
 PROVIDES += "kernel-module-compat"
diff --git a/recipes-connectivity/linux-mt76/files/src/firmware/mt7996_rom_patch.bin b/recipes-connectivity/linux-mt76/files/src/firmware/mt7996_rom_patch.bin
index c954b15..a734da1 100644
--- a/recipes-connectivity/linux-mt76/files/src/firmware/mt7996_rom_patch.bin
+++ b/recipes-connectivity/linux-mt76/files/src/firmware/mt7996_rom_patch.bin
Binary files differ
diff --git a/recipes-connectivity/linux-mt76/files/src/firmware/mt7996_wa.bin b/recipes-connectivity/linux-mt76/files/src/firmware/mt7996_wa.bin
index c239864..529ba6a 100644
--- a/recipes-connectivity/linux-mt76/files/src/firmware/mt7996_wa.bin
+++ b/recipes-connectivity/linux-mt76/files/src/firmware/mt7996_wa.bin
Binary files differ
diff --git a/recipes-connectivity/linux-mt76/files/src/firmware/mt7996_wm.bin b/recipes-connectivity/linux-mt76/files/src/firmware/mt7996_wm.bin
index dcfc7f4..8a0b654 100644
--- a/recipes-connectivity/linux-mt76/files/src/firmware/mt7996_wm.bin
+++ b/recipes-connectivity/linux-mt76/files/src/firmware/mt7996_wm.bin
Binary files differ
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988-clkitg.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988-clkitg.dtsi
index 48ed6c0..c4831a3 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988-clkitg.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988-clkitg.dtsi
@@ -110,7 +110,7 @@
 			<&topckgen CK_TOP_SPIM_MST_SEL>,
 			<&topckgen CK_TOP_NFI1X_SEL>,
 			<&topckgen CK_TOP_SPINFI_SEL>,
-			<&topckgen CK_TOP_PWM_SEL>,
+			<&system_clk>,
 			<&topckgen CK_TOP_I2C_SEL>,
 			<&topckgen CK_TOP_PCIE_MBIST_250M_SEL>,
 			<&system_clk>,
@@ -169,11 +169,11 @@
 			<&topckgen CK_TOP_ETH_MII_SEL>,
 			<&topckgen CK_TOP_CK_NPU_SEL_CM_TOPS_SEL>,
 			<&infracfg CK_INFRA_CK_F26M>,
-			<&infracfg CK_INFRA_PWM_O>,
 			<&system_clk>,
 			<&system_clk>,
 			<&system_clk>,
 			<&system_clk>,
+			<&system_clk>,
 			<&infracfg CK_INFRA_133M_HCK>,
 			<&infracfg CK_INFRA_133M_PHCK>,
 			<&infracfg CK_INFRA_66M_PHCK>,
@@ -215,16 +215,16 @@
 			<&infracfg CK_INFRA_USB_SYS_O>,
 			<&infracfg CK_INFRA_USB_SYS_O_P1>,
 			<&infracfg_ao CK_INFRA_66M_GPT_BCK>,
-			<&infracfg_ao CK_INFRA_66M_PWM_HCK>,
-			<&infracfg_ao CK_INFRA_66M_PWM_BCK>,
-			<&infracfg_ao CK_INFRA_66M_PWM_CK1>,
-			<&infracfg_ao CK_INFRA_66M_PWM_CK2>,
-			<&infracfg_ao CK_INFRA_66M_PWM_CK3>,
-			<&infracfg_ao CK_INFRA_66M_PWM_CK4>,
-			<&infracfg_ao CK_INFRA_66M_PWM_CK5>,
-			<&infracfg_ao CK_INFRA_66M_PWM_CK6>,
-			<&infracfg_ao CK_INFRA_66M_PWM_CK7>,
-			<&infracfg_ao CK_INFRA_66M_PWM_CK8>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
 			<&infracfg_ao CK_INFRA_133M_CQDMA_BCK>,
 			<&infracfg_ao CK_INFRA_66M_AUD_SLV_BCK>,
 			<&infracfg_ao CK_INFRA_AUD_26M>,
@@ -304,15 +304,15 @@
 			<&infracfg_ao CK_INFRA_MUX_SPI0_SEL>,
 			<&infracfg_ao CK_INFRA_MUX_SPI1_SEL>,
 			<&infracfg_ao CK_INFRA_MUX_SPI2_SEL>,
-			<&infracfg_ao CK_INFRA_PWM_SEL>,
-			<&infracfg_ao CK_INFRA_PWM_CK1_SEL>,
-			<&infracfg_ao CK_INFRA_PWM_CK2_SEL>,
-			<&infracfg_ao CK_INFRA_PWM_CK3_SEL>,
-			<&infracfg_ao CK_INFRA_PWM_CK4_SEL>,
-			<&infracfg_ao CK_INFRA_PWM_CK5_SEL>,
-			<&infracfg_ao CK_INFRA_PWM_CK6_SEL>,
-			<&infracfg_ao CK_INFRA_PWM_CK7_SEL>,
-			<&infracfg_ao CK_INFRA_PWM_CK8_SEL>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
+			<&system_clk>,
 			<&system_clk>,
 			<&system_clk>,
 			<&system_clk>,
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 274f897..e097cda 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
@@ -460,16 +460,16 @@
 		compatible = "mediatek,mt7988-pwm";
 		reg = <0 0x10048000 0 0x1000>;
 		#pwm-cells = <2>;
-		clocks = <&system_clk>,
-			 <&system_clk>,
-			 <&system_clk>,
-			 <&system_clk>,
-			 <&system_clk>,
-			 <&system_clk>,
-			 <&system_clk>,
-			 <&system_clk>,
-			 <&system_clk>,
-			 <&system_clk>;
+		clocks = <&infracfg_ao CK_INFRA_66M_PWM_BCK>,
+			 <&infracfg_ao CK_INFRA_66M_PWM_HCK>,
+			 <&infracfg_ao CK_INFRA_66M_PWM_CK1>,
+			 <&infracfg_ao CK_INFRA_66M_PWM_CK2>,
+			 <&infracfg_ao CK_INFRA_66M_PWM_CK3>,
+			 <&infracfg_ao CK_INFRA_66M_PWM_CK4>,
+			 <&infracfg_ao CK_INFRA_66M_PWM_CK5>,
+			 <&infracfg_ao CK_INFRA_66M_PWM_CK6>,
+			 <&infracfg_ao CK_INFRA_66M_PWM_CK7>,
+			 <&infracfg_ao CK_INFRA_66M_PWM_CK8>;
 		clock-names = "top", "main", "pwm1", "pwm2", "pwm3",
 			      "pwm4","pwm5","pwm6","pwm7","pwm8";
 		status = "disabled";
@@ -698,7 +698,7 @@
 		#gpio-cells = <2>;
 		gpio-ranges = <&pio 0 0 83>;
 		interrupt-controller;
-		interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-parent = <&gic>;
 		#interrupt-cells = <2>;
 	};
@@ -889,6 +889,11 @@
 		reg = <0 0x10003000 0 0x10>;
 	};
 
+	infra_bus_prot: infra_bus_prot@1000310c {
+		compatible = "mediatek,infracfg_ao_bus_hang_prot";
+		reg = <0 0x1000310c 0 0x14>;
+	};
+
 	spi0: spi@11007000 {
 		compatible = "mediatek,ipm-spi-quad";
 		reg = <0 0x11007000 0 0x100>;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/Makefile b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/Makefile
index 55e7465..b725c38 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/Makefile
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/Makefile
@@ -1 +1,2 @@
-obj-$(CONFIG_MTK_ICE_DEBUG) +=ice_debug/
+obj-$(CONFIG_MTK_ICE_DEBUG) += ice_debug/
+obj-y += infra_bus_prot/
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/infra_bus_prot/Makefile b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/infra_bus_prot/Makefile
new file mode 100644
index 0000000..e025a6d
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/infra_bus_prot/Makefile
@@ -0,0 +1 @@
+obj-y += infra_bus_prot.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/infra_bus_prot/infra_bus_prot.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/infra_bus_prot/infra_bus_prot.c
new file mode 100644
index 0000000..de2c841
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/misc/mediatek/infra_bus_prot/infra_bus_prot.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediatek bus hang protect driver
+ *
+ * Copyright (C) 2022 MediaTek Inc.
+ * Author: Sam Shih <sam.shih@mediatek.com>
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+#define	HANG_FREE_PROT_INFRA_AO		0x0
+
+/**
+ * struct mediatek_bus_prot - struct representing mediatek
+ * @regs: base address of PWM chip
+ */
+struct mediatek_bus_prot {
+	void __iomem *regs;
+};
+
+struct bus_hang_prot_of_data {
+	unsigned int offset;
+};
+
+static int mtk_bus_hang_prot_probe(struct platform_device *pdev)
+{
+	const struct bus_hang_prot_of_data *data;
+	struct resource *res;
+	void __iomem *regs;
+	int ret = 0;
+
+	data = of_device_get_match_data(&pdev->dev);
+	if (!data)
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(&pdev->dev, res);
+
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	writel(0x0, regs + data->offset);
+
+	return 0;
+}
+
+static const struct bus_hang_prot_of_data infracfg_ao_bus_hang_prot_data = {
+	.offset = HANG_FREE_PROT_INFRA_AO,
+};
+
+static const struct of_device_id bus_hang_prot_match[] = {
+	{
+		.compatible = "mediatek,infracfg_ao_bus_hang_prot",
+		.data = &infracfg_ao_bus_hang_prot_data
+	},
+	{ }
+};
+
+static struct platform_driver mtk_bus_hang_prot_driver = {
+	.probe = mtk_bus_hang_prot_probe,
+	.driver = {
+		.name = "mediatek,bus_hang_prot",
+		.of_match_table = bus_hang_prot_match,
+	},
+};
+
+static int __init mtk_bus_hang_prot_init(void)
+{
+	return platform_driver_register(&mtk_bus_hang_prot_driver);
+}
+
+arch_initcall(mtk_bus_hang_prot_init);
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 b22e359..688e319 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
@@ -486,3 +486,5 @@
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZONE_DMA32=y
+# CONFIG_BPF_KPROBE_OVERRIDE is not set
+# CONFIG_HIST_TRIGGERS is not set
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0950-pwm-mediatek-add-longer-period-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0950-pwm-mediatek-add-longer-period-support.patch
new file mode 100644
index 0000000..0934ae2
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0950-pwm-mediatek-add-longer-period-support.patch
@@ -0,0 +1,65 @@
+diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
+index 9701092..79d15a9 100644
+--- a/drivers/pwm/pwm-mediatek.c
++++ b/drivers/pwm/pwm-mediatek.c
+@@ -152,8 +152,11 @@ static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ 			       int duty_ns, int period_ns)
+ {
+ 	struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
+-	u32 clkdiv = 0, cnt_period, cnt_duty, reg_width = PWMDWIDTH,
+-	    reg_thres = PWMTHRES;
++	/* The source clock is divided by 2^clkdiv or iff the clksel bit
++	 * is set by (2^clkdiv*1625)
++	 */
++	u32 clkdiv = 0, clksel = 0, cnt_period, cnt_duty,
++	    reg_width = PWMDWIDTH, reg_thres = PWMTHRES;
+ 	u64 resolution;
+ 	int ret;
+ 
+@@ -164,12 +167,30 @@ static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ 
+ 	/* Using resolution in picosecond gets accuracy higher */
+ 	resolution = (u64)NSEC_PER_SEC * 1000;
++	/* Calculate resolution based on current clock frequency */
+ 	do_div(resolution, clk_get_rate(pc->clk_pwms[pwm->hwpwm]));
+-
++	/* Using resolution to calculate cnt_period which represents
++	 * the effective range of the PWM period counter
++	 */
+ 	cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution);
+ 	while (cnt_period > 8191) {
++		/* Using clkdiv to reduce clock frequency and calculate
++		 * new resolution based on new clock speed
++		 */
+ 		resolution *= 2;
+ 		clkdiv++;
++		if (clkdiv > PWM_CLK_DIV_MAX && !clksel) {
++			/* Using clksel to divide the pwm source clock by
++			 * an additional 1625, and recalculate new clkdiv
++			 * and resolution
++			 */
++			clksel = 1;
++			clkdiv = 0;
++			resolution = (u64)NSEC_PER_SEC * 1000 * 1625;
++			do_div(resolution,
++				clk_get_rate(pc->clk_pwms[pwm->hwpwm]));
++		}
++		/* Calculate cnt_period based on resolution */
+ 		cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000,
+ 						   resolution);
+ 	}
+@@ -189,8 +210,13 @@ static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ 		reg_thres = PWM45THRES_FIXUP;
+ 	}
+ 
++	/* Calculate cnt_duty based on resolution */
+ 	cnt_duty = DIV_ROUND_CLOSEST_ULL((u64)duty_ns * 1000, resolution);
+-	pwm_mediatek_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv);
++	if (clksel)
++		pwm_mediatek_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | BIT(3) |
++				    clkdiv);
++	else
++		pwm_mediatek_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv);
+ 	pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, cnt_period);
+ 	pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, cnt_duty);
+ 
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8009-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8009-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch
index 5bf48b2..36362f5 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8009-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8009-tphy-one-setting-of-TTSSC-Freq-Dev-for-all-IC-cases.patch
@@ -1,4 +1,4 @@
-From 917388b73b89f2859d795d800a296151d77e6ece Mon Sep 17 00:00:00 2001
+From 3295585b4e77f4a365bd1a4e17d8be6ee504584a Mon Sep 17 00:00:00 2001
 From: Zhanyong Wang <zhanyong.wang@mediatek.com>
 Date: Sat, 15 Oct 2022 17:38:54 +0800
 Subject: [PATCH 5/8] tphy: one setting of TTSSC-Freq-Dev for all IC cases
@@ -7,11 +7,11 @@
 
 Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
 ---
- drivers/phy/mediatek/phy-mtk-tphy.c | 18 ++++++++++++++++++
- 1 file changed, 18 insertions(+)
+ drivers/phy/mediatek/phy-mtk-tphy.c | 37 +++++++++++++++++++++++++++++
+ 1 file changed, 37 insertions(+)
 
 diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
-index a5b17a1aed5c..a38c50f4529f 100644
+index a5b17a1aed5c..49a2625c1fc1 100644
 --- a/drivers/phy/mediatek/phy-mtk-tphy.c
 +++ b/drivers/phy/mediatek/phy-mtk-tphy.c
 @@ -219,6 +219,14 @@
@@ -29,23 +29,56 @@
  #define U3P_SPLLC_XTALCTL3		0x018
  #define XC3_RG_U3_XTAL_RX_PWD		BIT(9)
  #define XC3_RG_U3_FRC_XTAL_RX_PWD	BIT(8)
-@@ -514,6 +522,16 @@ static void u3_phy_instance_init(struct mtk_tphy *tphy,
+@@ -373,6 +381,8 @@ struct mtk_phy_instance {
+ 	int eye_vrt;
+ 	int eye_term;
+ 	bool bc12_en;
++	bool u3_pll_ssc_delta;
++	bool u3_pll_ssc_delta1;
+ };
+ 
+ struct mtk_tphy {
+@@ -514,6 +524,20 @@ static void u3_phy_instance_init(struct mtk_tphy *tphy,
  	tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10);
  	writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET2);
  
-+	tmp = readl(u3_banks->phyd + U3P_U3_PHYD_REG19);
-+	tmp &= ~P3D_RG_PLL_SSC_DELTA1;
-+	tmp |= P3D_RG_PLL_SSC_DELTA1_VAL(0x1c3);
-+	writel(tmp, u3_banks->phyd + U3P_U3_PHYD_REG19);
++	if (instance->u3_pll_ssc_delta1) {
++		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_REG19);
++		tmp &= ~P3D_RG_PLL_SSC_DELTA1;
++		tmp |= P3D_RG_PLL_SSC_DELTA1_VAL(0x1c3);
++		writel(tmp, u3_banks->phyd + U3P_U3_PHYD_REG19);
++	}
 +
-+	tmp = readl(u3_banks->phyd + U3P_U3_PHYD_REG21);
-+	tmp &= ~P3D_RG_PLL_SSC_DELTA;
-+	tmp |= P3D_RG_PLL_SSC_DELTA_VAL(0x1c3);
-+	writel(tmp, u3_banks->phyd + U3P_U3_PHYD_REG21);
++	if (instance->u3_pll_ssc_delta) {
++		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_REG21);
++		tmp &= ~P3D_RG_PLL_SSC_DELTA;
++		tmp |= P3D_RG_PLL_SSC_DELTA_VAL(0x1c3);
++		writel(tmp, u3_banks->phyd + U3P_U3_PHYD_REG21);
++	}
 +
  	dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
  }
  
+@@ -942,6 +966,19 @@ static void phy_parse_property(struct mtk_tphy *tphy,
+ {
+ 	struct device *dev = &instance->phy->dev;
+ 
++	if (instance->type == PHY_TYPE_USB3) {
++		instance->u3_pll_ssc_delta =
++			device_property_read_bool(dev,
++				"mediatek,usb3-pll-ssc-delta");
++		instance->u3_pll_ssc_delta1 =
++			device_property_read_bool(dev,
++				"mediatek,usb3-pll-ssc-delta1");
++
++		dev_dbg(dev, "u3_pll_ssc_delta:%i, u3_pll_ssc_delta1:%i\n",
++					instance->u3_pll_ssc_delta,
++					instance->u3_pll_ssc_delta1);
++	}
++
+ 	if (instance->type != PHY_TYPE_USB2)
+ 		return;
+ 
 -- 
 2.18.0
 
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 8f6b290..f00effe 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
@@ -64,6 +64,7 @@
     file://0931-pwm-add-mt7981-support.patch \
     file://0932-add-pwm-feature-in-mt7988-project.patch \
     file://0950-add-pmic-config.patch \
+    file://0950-pwm-mediatek-add-longer-period-support.patch \
     file://0960-watchdog-add-mt7986-assert.patch \
     file://0990-gsw-rtl8367s-mt7622-support.patch \
     file://0991-dt-bindings-PCI-Mediatek-Update-PCIe-binding.patch \