[rdk-b][common][bsp][Refactor and sync kernel/wifi from Openwrt]
[Description]
Refactor and sync kernel/wifi from Openwrt
1.kernel: filogic880 initial version
[Release-log]
N/A
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0001-cpufreq-add-the-missing-platform-driver-unregister.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0001-cpufreq-add-the-missing-platform-driver-unregister.patch
new file mode 100644
index 0000000..fdf953d
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0001-cpufreq-add-the-missing-platform-driver-unregister.patch
@@ -0,0 +1,12 @@
+diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
+index 927ebc5..03bb7b5 100644
+--- a/drivers/cpufreq/mediatek-cpufreq.c
++++ b/drivers/cpufreq/mediatek-cpufreq.c
+@@ -573,6 +573,7 @@ static int __init mtk_cpufreq_driver_init(void)
+ pdev = platform_device_register_simple("mtk-cpufreq", -1, NULL, 0);
+ if (IS_ERR(pdev)) {
+ pr_err("failed to register mtk-cpufreq platform device\n");
++ platform_driver_unregister(&mtk_cpufreq_platdrv);
+ return PTR_ERR(pdev);
+ }
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0002-cpufreq-Enable-clocks-and-regulators.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0002-cpufreq-Enable-clocks-and-regulators.patch
new file mode 100644
index 0000000..2fa9359
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0002-cpufreq-Enable-clocks-and-regulators.patch
@@ -0,0 +1,88 @@
+diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
+index 03bb7b5..010a947 100644
+--- a/drivers/cpufreq/mediatek-cpufreq.c
++++ b/drivers/cpufreq/mediatek-cpufreq.c
+@@ -351,6 +351,12 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ goto out_free_resources;
+ }
+
++ ret = regulator_enable(proc_reg);
++ if (ret) {
++ dev_warn(cpu_dev, "cpu%d: failed to enable vproc\n", cpu);
++ goto out_free_resources;
++ }
++
+ /* Both presence and absence of sram regulator are valid cases. */
+ sram_reg = regulator_get_exclusive(cpu_dev, "sram");
+
+@@ -368,13 +374,21 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ goto out_free_resources;
+ }
+
++ ret = clk_prepare_enable(cpu_clk);
++ if (ret)
++ goto out_free_opp_table;
++
++ ret = clk_prepare_enable(inter_clk);
++ if (ret)
++ goto out_disable_mux_clock;
++
+ /* Search a safe voltage for intermediate frequency. */
+ rate = clk_get_rate(inter_clk);
+ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
+ if (IS_ERR(opp)) {
+ pr_err("failed to get intermediate opp for cpu%d\n", cpu);
+ ret = PTR_ERR(opp);
+- goto out_free_opp_table;
++ goto out_disable_inter_clock;
+ }
+ info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
+ dev_pm_opp_put(opp);
+@@ -393,10 +407,23 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+
+ return 0;
+
++out_disable_inter_clock:
++ if(!IS_ERR(inter_clk))
++ clk_disable_unprepare(inter_clk);
++
++out_disable_mux_clock:
++ if(!IS_ERR(cpu_clk))
++ clk_disable_unprepare(cpu_clk);
++
+ out_free_opp_table:
+ dev_pm_opp_of_cpumask_remove_table(&info->cpus);
+
+ out_free_resources:
++ if (!IS_ERR(proc_reg)) {
++ if (regulator_is_enabled(proc_reg))
++ regulator_disable(proc_reg);
++ }
++
+ if (!IS_ERR(proc_reg))
+ regulator_put(proc_reg);
+ if (!IS_ERR(sram_reg))
+@@ -411,14 +438,20 @@ out_free_resources:
+
+ static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
+ {
+- if (!IS_ERR(info->proc_reg))
++ if (!IS_ERR(info->proc_reg)){
++ regulator_disable(info->proc_reg);
+ regulator_put(info->proc_reg);
++ }
+ if (!IS_ERR(info->sram_reg))
+ regulator_put(info->sram_reg);
+- if (!IS_ERR(info->cpu_clk))
++ if (!IS_ERR(info->cpu_clk)){
++ clk_disable_unprepare(info->cpu_clk);
+ clk_put(info->cpu_clk);
+- if (!IS_ERR(info->inter_clk))
++ }
++ if (!IS_ERR(info->inter_clk)){
++ clk_disable_unprepare(info->inter_clk);
+ clk_put(info->inter_clk);
++ }
+
+ dev_pm_opp_of_cpumask_remove_table(&info->cpus);
+ }
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0003-clk-mtk-add-mt7988-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0003-clk-mtk-add-mt7988-support.patch
new file mode 100644
index 0000000..e673148
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0003-clk-mtk-add-mt7988-support.patch
@@ -0,0 +1,38 @@
+diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
+index 23393d5..cf3a53e 100644
+--- a/drivers/clk/mediatek/Kconfig
++++ b/drivers/clk/mediatek/Kconfig
+@@ -275,6 +275,14 @@ config COMMON_CLK_MT7981
+ This driver supports MediaTek MT7981 basic clocks and clocks
+ required for various periperals found on MediaTek.
+
++config COMMON_CLK_MT7988
++ bool "Clock driver for MediaTek MT7988"
++ depends on ARCH_MEDIATEK || COMPILE_TEST
++ select COMMON_CLK_MEDIATEK
++ ---help---
++ This driver supports MediaTek MT7988 basic clocks and clocks
++ required for various periperals found on MediaTek.
++
+ config COMMON_CLK_MT8135
+ bool "Clock driver for MediaTek MT8135"
+ depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
+diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
+index ffe0850..43ca85d 100644
+--- a/drivers/clk/mediatek/Makefile
++++ b/drivers/clk/mediatek/Makefile
+@@ -41,6 +41,7 @@ obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o
+ obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o
+ obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986.o
+ obj-$(CONFIG_COMMON_CLK_MT7981) += clk-mt7981.o
++obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988.o
+ obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
+ obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
+ obj-$(CONFIG_COMMON_CLK_MT8183) += clk-mt8183.o
+@@ -57,4 +58,4 @@ obj-$(CONFIG_COMMON_CLK_MT8183_VDECSYS) += clk-mt8183-vdec.o
+ obj-$(CONFIG_COMMON_CLK_MT8183_VENCSYS) += clk-mt8183-venc.o
+ obj-$(CONFIG_COMMON_CLK_MT8516) += clk-mt8516.o
+ obj-$(CONFIG_COMMON_CLK_MT8516_AUDSYS) += clk-mt8516-aud.o
+-obj-y += clk-bringup.o
+\ No newline at end of file
++obj-y += clk-bringup.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0003-cpufreq-add-mt7988a-spim-snand-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0003-cpufreq-add-mt7988a-spim-snand-support.patch
new file mode 100644
index 0000000..ee87f4e
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0003-cpufreq-add-mt7988a-spim-snand-support.patch
@@ -0,0 +1,212 @@
+diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
+index 010a947..291f629 100644
+--- a/drivers/cpufreq/mediatek-cpufreq.c
++++ b/drivers/cpufreq/mediatek-cpufreq.c
+@@ -38,6 +38,7 @@ struct mtk_cpu_dvfs_info {
+ struct regulator *proc_reg;
+ struct regulator *sram_reg;
+ struct clk *cpu_clk;
++ struct clk *cci_clk;
+ struct clk *inter_clk;
+ struct list_head list_head;
+ int intermediate_voltage;
+@@ -205,15 +206,24 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
+ struct cpufreq_frequency_table *freq_table = policy->freq_table;
+ struct clk *cpu_clk = policy->clk;
+ struct clk *armpll = clk_get_parent(cpu_clk);
++ struct clk *cci_clk = ERR_PTR(-ENODEV);
++ struct clk *ccipll;
+ struct mtk_cpu_dvfs_info *info = policy->driver_data;
+ struct device *cpu_dev = info->cpu_dev;
+ struct dev_pm_opp *opp;
+- long freq_hz, old_freq_hz;
++ long freq_hz, old_freq_hz, cci_freq_hz, cci_old_freq_hz;
+ int vproc, old_vproc, inter_vproc, target_vproc, ret;
+
+ inter_vproc = info->intermediate_voltage;
+
+ old_freq_hz = clk_get_rate(cpu_clk);
++
++ if (!IS_ERR(info->cci_clk)) {
++ cci_clk = info->cci_clk;
++ ccipll = clk_get_parent(cci_clk);
++ cci_old_freq_hz = clk_get_rate(cci_clk);
++ }
++
+ old_vproc = regulator_get_voltage(info->proc_reg);
+ if (old_vproc < 0) {
+ pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc);
+@@ -221,6 +231,7 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
+ }
+
+ freq_hz = freq_table[index].frequency * 1000;
++ cci_freq_hz = freq_table[index].frequency * 600;
+
+ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
+ if (IS_ERR(opp)) {
+@@ -246,6 +257,18 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
+ }
+ }
+
++ /* Reparent the CCI clock to intermediate clock. */
++ if (!IS_ERR(cci_clk)) {
++ ret = clk_set_parent(cci_clk, info->inter_clk);
++ if (ret) {
++ pr_err("cpu%d: failed to re-parent cci clock!\n",
++ policy->cpu);
++ mtk_cpufreq_set_voltage(info, old_vproc);
++ WARN_ON(1);
++ return ret;
++ }
++ }
++
+ /* Reparent the CPU clock to intermediate clock. */
+ ret = clk_set_parent(cpu_clk, info->inter_clk);
+ if (ret) {
+@@ -266,6 +289,18 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
+ return ret;
+ }
+
++ /* Set the original PLL to target rate. */
++ if (!IS_ERR(cci_clk)) {
++ ret = clk_set_rate(ccipll, cci_freq_hz);
++ if (ret) {
++ pr_err("cpu%d: failed to scale cci clock rate!\n",
++ policy->cpu);
++ clk_set_parent(cci_clk, ccipll);
++ mtk_cpufreq_set_voltage(info, old_vproc);
++ return ret;
++ }
++ }
++
+ /* Set parent of CPU clock back to the original PLL. */
+ ret = clk_set_parent(cpu_clk, armpll);
+ if (ret) {
+@@ -276,6 +311,17 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
+ return ret;
+ }
+
++ /* Set parent of CCI clock back to the original PLL. */
++ if (!IS_ERR(cci_clk)) {
++ ret = clk_set_parent(cci_clk, ccipll);
++ if (ret) {
++ pr_err("cpu%d: failed to re-parent cci clock!\n",
++ policy->cpu);
++ mtk_cpufreq_set_voltage(info, inter_vproc);
++ WARN_ON(1);
++ return ret;
++ }
++ }
+ /*
+ * If the new voltage is lower than the intermediate voltage or the
+ * original voltage, scale down to the new voltage.
+@@ -285,9 +331,20 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
+ if (ret) {
+ pr_err("cpu%d: failed to scale down voltage!\n",
+ policy->cpu);
++ if (!IS_ERR(cci_clk))
++ clk_set_parent(cci_clk, info->inter_clk);
++
+ clk_set_parent(cpu_clk, info->inter_clk);
+ clk_set_rate(armpll, old_freq_hz);
++
++ if (!IS_ERR(cci_clk))
++ clk_set_rate(ccipll, cci_old_freq_hz);
++
+ clk_set_parent(cpu_clk, armpll);
++
++ if (!IS_ERR(cci_clk))
++ clk_set_parent(cci_clk, ccipll);
++
+ return ret;
+ }
+ }
+@@ -303,6 +360,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ struct regulator *proc_reg = ERR_PTR(-ENODEV);
+ struct regulator *sram_reg = ERR_PTR(-ENODEV);
+ struct clk *cpu_clk = ERR_PTR(-ENODEV);
++ struct clk *cci_clk = ERR_PTR(-ENODEV);
+ struct clk *inter_clk = ERR_PTR(-ENODEV);
+ struct dev_pm_opp *opp;
+ unsigned long rate;
+@@ -338,6 +396,8 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ goto out_free_resources;
+ }
+
++ cci_clk = clk_get(cpu_dev, "cci");
++
+ proc_reg = regulator_get_optional(cpu_dev, "proc");
+ if (IS_ERR(proc_reg)) {
+ if (PTR_ERR(proc_reg) == -EPROBE_DEFER)
+@@ -379,16 +439,23 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ goto out_free_opp_table;
+
+ ret = clk_prepare_enable(inter_clk);
++
+ if (ret)
+ goto out_disable_mux_clock;
+
++ if(!(IS_ERR(cci_clk))) {
++ ret = clk_prepare_enable(cci_clk);
++ if(ret)
++ goto out_disable_inter_clock;
++ }
++
+ /* Search a safe voltage for intermediate frequency. */
+ rate = clk_get_rate(inter_clk);
+ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate);
+ if (IS_ERR(opp)) {
+ pr_err("failed to get intermediate opp for cpu%d\n", cpu);
+ ret = PTR_ERR(opp);
+- goto out_disable_inter_clock;
++ goto out_disable_cci_clock;
+ }
+ info->intermediate_voltage = dev_pm_opp_get_voltage(opp);
+ dev_pm_opp_put(opp);
+@@ -397,6 +464,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+ info->proc_reg = proc_reg;
+ info->sram_reg = IS_ERR(sram_reg) ? NULL : sram_reg;
+ info->cpu_clk = cpu_clk;
++ info->cci_clk = cci_clk;
+ info->inter_clk = inter_clk;
+
+ /*
+@@ -407,6 +475,10 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
+
+ return 0;
+
++out_disable_cci_clock:
++ if(!IS_ERR(cci_clk))
++ clk_disable_unprepare(cci_clk);
++
+ out_disable_inter_clock:
+ if(!IS_ERR(inter_clk))
+ clk_disable_unprepare(inter_clk);
+@@ -432,6 +504,8 @@ out_free_resources:
+ clk_put(cpu_clk);
+ if (!IS_ERR(inter_clk))
+ clk_put(inter_clk);
++ if (!IS_ERR(cci_clk))
++ clk_put(cci_clk);
+
+ return ret;
+ }
+@@ -452,6 +526,10 @@ static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info)
+ clk_disable_unprepare(info->inter_clk);
+ clk_put(info->inter_clk);
+ }
++ if (!IS_ERR(info->cci_clk)){
++ clk_disable_unprepare(info->cci_clk);
++ clk_put(info->cci_clk);
++ }
+
+ dev_pm_opp_of_cpumask_remove_table(&info->cpus);
+ }
+@@ -570,6 +648,7 @@ static const struct of_device_id mtk_cpufreq_machines[] __initconst = {
+ { .compatible = "mediatek,mt8176", },
+ { .compatible = "mediatek,mt8183", },
+ { .compatible = "mediatek,mt8516", },
++ { .compatible = "mediatek,mt7988", },
+
+ { }
+ };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0005-clk-mtk-add-chg-shift-control.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0005-clk-mtk-add-chg-shift-control.patch
new file mode 100644
index 0000000..4a9ff6f
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0005-clk-mtk-add-chg-shift-control.patch
@@ -0,0 +1,28 @@
+diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
+index c3d6756..d84c45d 100644
+--- a/drivers/clk/mediatek/clk-mtk.h
++++ b/drivers/clk/mediatek/clk-mtk.h
+@@ -231,6 +231,7 @@ struct mtk_pll_data {
+ uint32_t pcw_reg;
+ int pcw_shift;
+ uint32_t pcw_chg_reg;
++ int pcw_chg_shift;
+ const struct mtk_pll_div_table *div_table;
+ const char *parent_name;
+ };
+diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
+index f440f2c..db318fe 100644
+--- a/drivers/clk/mediatek/clk-pll.c
++++ b/drivers/clk/mediatek/clk-pll.c
+@@ -136,7 +136,10 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
+ pll->data->pcw_shift);
+ val |= pcw << pll->data->pcw_shift;
+ writel(val, pll->pcw_addr);
+- chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK;
++ if (pll->data->pcw_chg_shift)
++ chg = readl(pll->pcw_chg_addr) | BIT(pll->data->pcw_chg_shift);
++ else
++ chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK;
+ writel(chg, pll->pcw_chg_addr);
+ if (pll->tuner_addr)
+ writel(val + 1, pll->tuner_addr);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0006-powerdomain-add-mt7988-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0006-powerdomain-add-mt7988-support.patch
new file mode 100644
index 0000000..7fc4f1d
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0006-powerdomain-add-mt7988-support.patch
@@ -0,0 +1,9 @@
+diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
+index b017330..1c485e3 100644
+--- a/drivers/soc/mediatek/Makefile
++++ b/drivers/soc/mediatek/Makefile
+@@ -3,3 +3,4 @@ obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
+ obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
+ obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
+ obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
++obj-$(CONFIG_MTK_SCPSYS) += mtk-pm-domains.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0007-cpufreq-mtk-vbining-add-mt7988-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0007-cpufreq-mtk-vbining-add-mt7988-support.patch
new file mode 100644
index 0000000..8e99118
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0007-cpufreq-mtk-vbining-add-mt7988-support.patch
@@ -0,0 +1,47 @@
+diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
+index b23b6d2..147a224 100644
+--- a/drivers/cpufreq/mediatek-cpufreq.c
++++ b/drivers/cpufreq/mediatek-cpufreq.c
+@@ -15,6 +15,7 @@
+ #include <linux/regulator/consumer.h>
+ #include <linux/slab.h>
+ #include <linux/thermal.h>
++#include <linux/nvmem-consumer.h>
+
+ #define MIN_VOLT_SHIFT (100000)
+ #define MAX_VOLT_SHIFT (200000)
+@@ -539,6 +540,11 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
+ struct mtk_cpu_dvfs_info *info;
+ struct cpufreq_frequency_table *freq_table;
+ int ret;
++ int target_vproc;
++ u32 reg_val;
++ struct nvmem_cell *cell;
++ size_t len;
++ u32 *buf;
+
+ info = mtk_cpu_dvfs_info_lookup(policy->cpu);
+ if (!info) {
+@@ -547,6 +553,22 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
+ return -EINVAL;
+ }
+
++ cell = nvmem_cell_get(info->cpu_dev, "calibration-data");
++ if (!IS_ERR(cell)) {
++ buf = (u32 *)nvmem_cell_read(cell, &len);
++ nvmem_cell_put(cell);
++ if (!IS_ERR(buf)) {
++ reg_val = buf[0] & 0x1f;
++ pr_debug("%s: read vbinning value: %d\n", __func__, reg_val);
++ if (reg_val > 0) {
++ target_vproc = 850000 + reg_val * 10000;
++ dev_pm_opp_remove(info->cpu_dev, 1800000000);
++ dev_pm_opp_add(info->cpu_dev, 1800000000, target_vproc);
++ }
++ kfree(buf);
++ }
++ }
++
+ ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table);
+ if (ret) {
+ pr_err("failed to init cpufreq table for cpu%d: %d\n",
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0505-crypto-add-eip197-inside-secure-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0505-crypto-add-eip197-inside-secure-support.patch
index ed30817..eff209b 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0505-crypto-add-eip197-inside-secure-support.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0505-crypto-add-eip197-inside-secure-support.patch
@@ -12,7 +12,14 @@
}
}
-@@ -409,7 +414,7 @@
+@@ -403,13 +408,13 @@
+ const struct firmware *fw[FW_NB];
+ char fw_path[37], *dir = NULL;
+ int i, j, ret = 0, pe;
+- int ipuesz, ifppsz, minifw = 0;
++ int ipuesz, ifppsz, minifw = 1;
+
+ if (priv->version == EIP197D_MRVL)
dir = "eip197d";
else if (priv->version == EIP197B_MRVL ||
priv->version == EIP197_DEVBRD)
@@ -21,7 +28,19 @@
else
return -ENODEV;
-@@ -792,6 +797,12 @@
+@@ -592,6 +597,11 @@
+ */
+ if (priv->flags & SAFEXCEL_HW_EIP197) {
+ val = readl(EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL);
++ /* Clear axi_burst_size and rx_burst_size */
++ val &= 0xffffff00;
++ /* Set axi_burst_size = 3, rx_burst_size = 3 */
++ val |= EIP197_MST_CTRL_RD_CACHE(3);
++ val |= EIP197_MST_CTRL_WD_CACHE(3);
+ val |= EIP197_MST_CTRL_TX_MAX_CMD(5);
+ writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL);
+ }
+@@ -792,6 +802,12 @@
return ret;
}
@@ -34,7 +53,7 @@
return safexcel_hw_setup_cdesc_rings(priv) ?:
safexcel_hw_setup_rdesc_rings(priv) ?:
0;
-@@ -1498,6 +1509,9 @@
+@@ -1498,6 +1514,9 @@
hwopt = readl(EIP197_GLOBAL(priv) + EIP197_OPTIONS);
hiaopt = readl(EIP197_HIA_AIC(priv) + EIP197_HIA_OPTIONS);
@@ -44,7 +63,7 @@
if (priv->flags & SAFEXCEL_HW_EIP197) {
/* EIP197 */
peopt = readl(EIP197_PE(priv) + EIP197_PE_OPTIONS(0));
-@@ -1516,8 +1530,37 @@
+@@ -1516,8 +1535,37 @@
EIP197_N_RINGS_MASK;
if (hiaopt & EIP197_HIA_OPT_HAS_PE_ARB)
priv->flags |= EIP197_PE_ARB;
@@ -83,7 +102,7 @@
/* If not a full TRC, then assume simple TRC */
if (!(hwopt & EIP197_OPT_HAS_TRC))
priv->flags |= EIP197_SIMPLE_TRC;
-@@ -1555,13 +1598,14 @@
+@@ -1555,13 +1603,14 @@
EIP197_PE_EIP96_OPTIONS(0));
/* Print single info line describing what we just detected */
@@ -100,7 +119,7 @@
safexcel_configure(priv);
-@@ -1690,6 +1734,7 @@
+@@ -1690,6 +1739,7 @@
{
struct device *dev = &pdev->dev;
struct safexcel_crypto_priv *priv;
@@ -108,7 +127,7 @@
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-@@ -1701,7 +1746,11 @@
+@@ -1701,7 +1751,11 @@
platform_set_drvdata(pdev, priv);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0932-add-pwm-feature-in-mt7988-project.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0932-add-pwm-feature-in-mt7988-project.patch
new file mode 100644
index 0000000..8268e7d
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0932-add-pwm-feature-in-mt7988-project.patch
@@ -0,0 +1,25 @@
+diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
+index 3a5a456..6d6206e 100644
+--- a/drivers/pwm/pwm-mediatek.c
++++ b/drivers/pwm/pwm-mediatek.c
+@@ -350,6 +350,12 @@ static const struct pwm_mediatek_of_data mt7986_pwm_data = {
+ .reg_ver = REG_V2,
+ };
+
++static const struct pwm_mediatek_of_data mt7988_pwm_data = {
++ .num_pwms = 8,
++ .pwm45_fixup = false,
++ .reg_ver = REG_V2,
++};
++
+ static const struct pwm_mediatek_of_data mt8516_pwm_data = {
+ .num_pwms = 5,
+ .pwm45_fixup = false,
+@@ -364,6 +370,7 @@ static const struct of_device_id pwm_mediatek_of_match[] = {
+ { .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data },
+ { .compatible = "mediatek,mt7981-pwm", .data = &mt7981_pwm_data },
+ { .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data },
++ { .compatible = "mediatek,mt7988-pwm", .data = &mt7988_pwm_data },
+ { .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data },
+ { },
+ };
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0950-add-pmic-config.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0950-add-pmic-config.patch
new file mode 100644
index 0000000..f5384f3
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/0950-add-pmic-config.patch
@@ -0,0 +1,36 @@
+diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
+index 3ee6353..2e393a7 100644
+--- a/drivers/regulator/Kconfig
++++ b/drivers/regulator/Kconfig
+@@ -798,6 +798,16 @@ config REGULATOR_RT5033
+ RT5033 PMIC. The device supports multiple regulators like
+ current source, LDO and Buck.
+
++config REGULATOR_RT5190A
++ tristate "Richtek RT5190A PMIC"
++ depends on I2C
++ select REGMAP_I2C
++ help
++ This add support for voltage regulator in Ritchtek RT5190A PMIC.
++ It integrates 1 channel buck controller, 3 channels high efficiency
++ buck converters, 1 LDO, mute AC OFF depop function, with the general
++ I2C control interface.
++
+ config REGULATOR_S2MPA01
+ tristate "Samsung S2MPA01 voltage regulator"
+ depends on MFD_SEC_CORE
+diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
+index 2210ba5..bf75b77 100644
+--- a/drivers/regulator/Makefile
++++ b/drivers/regulator/Makefile
+@@ -100,6 +100,7 @@ obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
+ obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o
+ obj-$(CONFIG_REGULATOR_RN5T618) += rn5t618-regulator.o
+ obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o
++obj-$(CONFIG_REGULATOR_RT5190A) += rt5190a-regulator.o
+ obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
+ obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
+ obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1662-trng-Add-trng-support-for-mt7988.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1662-trng-Add-trng-support-for-mt7988.patch
new file mode 100644
index 0000000..a8f1dfe
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/1662-trng-Add-trng-support-for-mt7988.patch
@@ -0,0 +1,38 @@
+From cbd37bfc8221c1a81d235ddfb1898536a821c650 Mon Sep 17 00:00:00 2001
+From: "mingming.su" <Mingming.Su@mediatek.com>
+Date: Wed, 7 Sep 2022 15:44:46 +0800
+Subject: [PATCH] trng: Add trng support for mt7988
+
+Add trng support for mt7988.
+
+Signed-off-by: mingming.su <Mingming.Su@mediatek.com>
+---
+ drivers/char/hw_random/mtk-rng.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c
+index 75fca4cef..878170c15 100644
+--- a/drivers/char/hw_random/mtk-rng.c
++++ b/drivers/char/hw_random/mtk-rng.c
+@@ -231,6 +231,10 @@ static const struct mtk_rng_of_data mt7986_rng_data = {
+ .rng_version = 1,
+ };
+
++static const struct mtk_rng_of_data mt7988_rng_data = {
++ .rng_version = 2,
++};
++
+ static const struct mtk_rng_of_data mt7623_rng_data = {
+ .rng_version = 1,
+ };
+@@ -238,6 +242,7 @@ static const struct mtk_rng_of_data mt7623_rng_data = {
+ static const struct of_device_id mtk_rng_match[] = {
+ { .compatible = "mediatek,mt7981-rng", .data = &mt7981_rng_data },
+ { .compatible = "mediatek,mt7986-rng", .data = &mt7986_rng_data },
++ { .compatible = "mediatek,mt7988-rng", .data = &mt7988_rng_data },
+ { .compatible = "mediatek,mt7623-rng", .data = &mt7623_rng_data },
+ {},
+ };
+--
+2.18.0
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/401-pinctrl-enable-mt7988-pinctrl-config.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/401-pinctrl-enable-mt7988-pinctrl-config.patch
new file mode 100644
index 0000000..01f01f6
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/401-pinctrl-enable-mt7988-pinctrl-config.patch
@@ -0,0 +1,30 @@
+diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig
+index e7ec276..b6341dd 100644
+--- a/drivers/pinctrl/mediatek/Kconfig
++++ b/drivers/pinctrl/mediatek/Kconfig
+@@ -112,6 +112,13 @@ config PINCTRL_MT7986
+ default ARM64 && ARCH_MEDIATEK
+ select PINCTRL_MTK_MOORE
+
++config PINCTRL_MT7988
++ bool "Mediatek MT7988 pin control"
++ depends on OF
++ depends on ARM64 || COMPILE_TEST
++ default ARM64 && ARCH_MEDIATEK
++ select PINCTRL_MTK_MOORE
++
+ config PINCTRL_MT8173
+ bool "Mediatek MT8173 pin control"
+ depends on OF
+diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile
+index e6813cf..6e28df9 100644
+--- a/drivers/pinctrl/mediatek/Makefile
++++ b/drivers/pinctrl/mediatek/Makefile
+@@ -17,6 +17,7 @@ obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o
+ obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o
+ obj-$(CONFIG_PINCTRL_MT7981) += pinctrl-mt7981.o
+ obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o
++obj-$(CONFIG_PINCTRL_MT7988) += pinctrl-mt7988.o
+ obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o
+ obj-$(CONFIG_PINCTRL_MT8183) += pinctrl-mt8183.o
+ obj-$(CONFIG_PINCTRL_MT8516) += pinctrl-mt8516.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/6001-mtk-thermal-add-lvts-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/6001-mtk-thermal-add-lvts-support.patch
new file mode 100644
index 0000000..1591144
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/6001-mtk-thermal-add-lvts-support.patch
@@ -0,0 +1,28 @@
+diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
+index 001a21ab..67d3da48 100644
+--- a/drivers/thermal/Kconfig
++++ b/drivers/thermal/Kconfig
+@@ -348,6 +348,11 @@ config MTK_THERMAL
+ Enable this option if you want to have support for thermal management
+ controller present in Mediatek SoCs
+
++menu "Mediatek thermal drivers"
++depends on ARCH_MEDIATEK || COMPILE_TEST
++source "drivers/thermal/mediatek/Kconfig"
++endmenu
++
+ menu "Intel thermal drivers"
+ depends on X86 || X86_INTEL_QUARK || COMPILE_TEST
+ source "drivers/thermal/intel/Kconfig"
+diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
+index 74a37c7f..6be9ff19 100644
+--- a/drivers/thermal/Makefile
++++ b/drivers/thermal/Makefile
+@@ -51,6 +51,7 @@ obj-$(CONFIG_QCOM_TSENS) += qcom/
+ obj-y += tegra/
+ obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
+ obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
++obj-y += mediatek/
+ obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
+ obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
+ obj-$(CONFIG_UNIPHIER_THERMAL) += uniphier_thermal.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch
new file mode 100644
index 0000000..a102660
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/746-add-mediatek-2p5ge-phy-support.patch
@@ -0,0 +1,24 @@
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -522,6 +522,11 @@ config MEDIATEK_GE_PHY
+ help
+ Supports the MediaTek Gigabit Ethernet PHYs.
+
++config MEDIATEK_2P5GE_PHY
++ tristate "MediaTek 2.5Gb Ethernet PHYs"
++ ---help---
++ Supports MediaTek internal 2.5Gb Ethernet PHYs.
++
+ config MICREL_PHY
+ tristate "Micrel PHYs"
+ ---help---
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -95,6 +95,7 @@ obj-$(CONFIG_LXT_PHY) += lxt.o
+ obj-$(CONFIG_MARVELL_PHY) += marvell.o
+ obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o
+ obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
++obj-$(CONFIG_MEDIATEK_2P5GE_PHY)+= mediatek-2p5ge.o
+ obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
+ obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
+ obj-$(CONFIG_MICREL_PHY) += micrel.o
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/748-add-netlink-support-for-dsa.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/748-add-netlink-support-for-dsa.patch
new file mode 100644
index 0000000..8853324
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/748-add-netlink-support-for-dsa.patch
@@ -0,0 +1,498 @@
+Index: linux-5.4.203/drivers/net/dsa/Makefile
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/Makefile
++++ linux-5.4.203/drivers/net/dsa/Makefile
+@@ -7,7 +7,7 @@ obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdi
+ endif
+ obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
+ obj-$(CONFIG_NET_DSA_MT7530) += mt7530-dsa.o
+-mt7530-dsa-objs := mt7530.o mt7531_phy.o
++mt7530-dsa-objs := mt7530.o mt7530_nl.o mt7531_phy.o
+ obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
+ obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
+ obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
+Index: linux-5.4.203/drivers/net/dsa/mt7530.c
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/mt7530.c
++++ linux-5.4.203/drivers/net/dsa/mt7530.c
+@@ -21,6 +21,7 @@
+ #include <net/dsa.h>
+
+ #include "mt7530.h"
++#include "mt7530_nl.h"
+
+ /* String, offset, and register size in bytes if different from 4 bytes */
+ static const struct mt7530_mib_desc mt7530_mib[] = {
+@@ -222,7 +223,7 @@ mt7530_mii_read(struct mt7530_priv *priv
+ return (hi << 16) | (lo & 0xffff);
+ }
+
+-static void
++void
+ mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val)
+ {
+ struct mii_bus *bus = priv->bus;
+@@ -255,7 +256,7 @@ _mt7530_read(struct mt7530_dummy_poll *p
+ return val;
+ }
+
+-static u32
++u32
+ mt7530_read(struct mt7530_priv *priv, u32 reg)
+ {
+ struct mt7530_dummy_poll p;
+@@ -614,7 +615,7 @@ static int mt7530_phy_write(struct dsa_s
+ return mdiobus_write_nested(priv->bus, port, regnum, val);
+ }
+
+-static int
++int
+ mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
+ int regnum)
+ {
+@@ -663,7 +664,7 @@ out:
+ return ret;
+ }
+
+-static int
++int
+ mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
+ int regnum, u32 data)
+ {
+@@ -711,7 +712,7 @@ out:
+ return ret;
+ }
+
+-static int
++int
+ mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
+ {
+ struct mii_bus *bus = priv->bus;
+@@ -749,7 +750,7 @@ out:
+ return ret;
+ }
+
+-static int
++int
+ mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
+ u16 data)
+ {
+@@ -2690,6 +2691,7 @@ mt7530_probe(struct mdio_device *mdiodev
+ {
+ struct mt7530_priv *priv;
+ struct device_node *dn;
++ int ret;
+
+ dn = mdiodev->dev.of_node;
+
+@@ -2765,7 +2767,13 @@ mt7530_probe(struct mdio_device *mdiodev
+ mutex_init(&priv->reg_mutex);
+ dev_set_drvdata(&mdiodev->dev, priv);
+
+- return dsa_register_switch(priv->ds);
++ ret = dsa_register_switch(priv->ds);
++ if (ret)
++ return ret;
++
++ mt7530_nl_init(&priv);
++
++ return 0;
+ }
+
+ static void
+@@ -2786,6 +2794,8 @@ mt7530_remove(struct mdio_device *mdiode
+
+ dsa_unregister_switch(priv->ds);
+ mutex_destroy(&priv->reg_mutex);
++
++ mt7530_nl_exit();
+ }
+
+ static struct mdio_driver mt7530_mdio_driver = {
+Index: linux-5.4.203/drivers/net/dsa/mt7530.h
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/mt7530.h
++++ linux-5.4.203/drivers/net/dsa/mt7530.h
+@@ -783,4 +783,12 @@ static inline void INIT_MT7530_DUMMY_POL
+ }
+
+ int mt7531_phy_setup(struct dsa_switch *ds);
++u32 mt7530_read(struct mt7530_priv *priv, u32 reg);
++void mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val);
++int mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad, int regnum);
++int mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad, int regnum, u32 data);
++int mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum);
++int mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum, u16 data);
++
++
+ #endif /* __MT7530_H */
+Index: linux-5.4.203/drivers/net/dsa/mt7530_nl.c
+===================================================================
+--- /dev/null
++++ linux-5.4.203/drivers/net/dsa/mt7530_nl.c
+@@ -0,0 +1,311 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2018 MediaTek Inc.
++ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
++ */
++
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <net/genetlink.h>
++#include <linux/of_mdio.h>
++#include <linux/phylink.h>
++#include <net/dsa.h>
++
++#include "mt7530.h"
++#include "mt7530_nl.h"
++
++struct mt7530_nl_cmd_item {
++ enum mt7530_cmd cmd;
++ bool require_dev;
++ int (*process)(struct genl_info *info);
++ u32 nr_required_attrs;
++ const enum mt7530_attr *required_attrs;
++};
++
++struct mt7530_priv *sw_priv;
++
++static DEFINE_MUTEX(mt7530_devs_lock);
++
++void mt7530_put(void)
++{
++ mutex_unlock(&mt7530_devs_lock);
++}
++
++void mt7530_lock(void)
++{
++ mutex_lock(&mt7530_devs_lock);
++}
++
++static int mt7530_nl_response(struct sk_buff *skb, struct genl_info *info);
++
++static const struct nla_policy mt7530_nl_cmd_policy[] = {
++ [MT7530_ATTR_TYPE_MESG] = { .type = NLA_STRING },
++ [MT7530_ATTR_TYPE_PHY] = { .type = NLA_S32 },
++ [MT7530_ATTR_TYPE_REG] = { .type = NLA_S32 },
++ [MT7530_ATTR_TYPE_VAL] = { .type = NLA_S32 },
++ [MT7530_ATTR_TYPE_DEV_NAME] = { .type = NLA_S32 },
++ [MT7530_ATTR_TYPE_DEV_ID] = { .type = NLA_S32 },
++ [MT7530_ATTR_TYPE_DEVAD] = { .type = NLA_S32 },
++};
++
++static const struct genl_ops mt7530_nl_ops[] = {
++ {
++ .cmd = MT7530_CMD_REQUEST,
++ .doit = mt7530_nl_response,
++ .flags = GENL_ADMIN_PERM,
++ }, {
++ .cmd = MT7530_CMD_READ,
++ .doit = mt7530_nl_response,
++ .flags = GENL_ADMIN_PERM,
++ }, {
++ .cmd = MT7530_CMD_WRITE,
++ .doit = mt7530_nl_response,
++ .flags = GENL_ADMIN_PERM,
++ },
++};
++
++static struct genl_family mt7530_nl_family = {
++ .name = MT7530_DSA_GENL_NAME,
++ .version = MT7530_GENL_VERSION,
++ .maxattr = MT7530_NR_ATTR_TYPE,
++ .ops = mt7530_nl_ops,
++ .n_ops = ARRAY_SIZE(mt7530_nl_ops),
++ .policy = mt7530_nl_cmd_policy,
++};
++
++static int mt7530_nl_prepare_reply(struct genl_info *info, u8 cmd,
++ struct sk_buff **skbp)
++{
++ struct sk_buff *msg;
++ void *reply;
++
++ if (!info)
++ return -EINVAL;
++
++ msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
++ if (!msg)
++ return -ENOMEM;
++
++ /* Construct send-back message header */
++ reply = genlmsg_put(msg, info->snd_portid, info->snd_seq,
++ &mt7530_nl_family, 0, cmd);
++ if (!reply) {
++ nlmsg_free(msg);
++ return -EINVAL;
++ }
++
++ *skbp = msg;
++ return 0;
++}
++
++static int mt7530_nl_send_reply(struct sk_buff *skb, struct genl_info *info)
++{
++ struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
++ void *reply = genlmsg_data(genlhdr);
++
++ /* Finalize a generic netlink message (update message header) */
++ genlmsg_end(skb, reply);
++
++ /* reply to a request */
++ return genlmsg_reply(skb, info);
++}
++
++static s32 mt7530_nl_get_s32(struct genl_info *info, enum mt7530_attr attr,
++ s32 defval)
++{
++ struct nlattr *na;
++
++ na = info->attrs[attr];
++ if (na)
++ return nla_get_s32(na);
++
++ return defval;
++}
++
++static int mt7530_nl_get_u32(struct genl_info *info, enum mt7530_attr attr,
++ u32 *val)
++{
++ struct nlattr *na;
++
++ na = info->attrs[attr];
++ if (na) {
++ *val = nla_get_u32(na);
++ return 0;
++ }
++
++ return -1;
++}
++
++static int mt7530_nl_reply_read(struct genl_info *info)
++{
++ struct sk_buff *rep_skb = NULL;
++ s32 phy, devad, reg;
++ int value;
++ int ret = 0;
++
++ phy = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_PHY, -1);
++ devad = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_DEVAD, -1);
++ reg = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_REG, -1);
++
++ if (reg < 0)
++ goto err;
++
++ ret = mt7530_nl_prepare_reply(info, MT7530_CMD_READ, &rep_skb);
++ if (ret < 0)
++ goto err;
++
++ if (phy >= 0) {
++ if (devad < 0)
++ value = mt7531_ind_c22_phy_read(sw_priv, phy, reg);
++ else
++ value = mt7531_ind_c45_phy_read(sw_priv, phy, devad, reg);
++ } else
++ value = mt7530_read(sw_priv, reg);
++
++ ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_REG, reg);
++ if (ret < 0)
++ goto err;
++
++ ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_VAL, value);
++ if (ret < 0)
++ goto err;
++
++ return mt7530_nl_send_reply(rep_skb, info);
++
++err:
++ if (rep_skb)
++ nlmsg_free(rep_skb);
++
++ return ret;
++}
++
++static int mt7530_nl_reply_write(struct genl_info *info)
++{
++ struct sk_buff *rep_skb = NULL;
++ s32 phy, devad, reg;
++ u32 value;
++ int ret = 0;
++
++ phy = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_PHY, -1);
++ devad = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_DEVAD, -1);
++ reg = mt7530_nl_get_s32(info, MT7530_ATTR_TYPE_REG, -1);
++
++ if (mt7530_nl_get_u32(info, MT7530_ATTR_TYPE_VAL, &value))
++ goto err;
++
++ if (reg < 0)
++ goto err;
++
++ ret = mt7530_nl_prepare_reply(info, MT7530_CMD_WRITE, &rep_skb);
++ if (ret < 0)
++ goto err;
++
++ if (phy >= 0) {
++ if (devad < 0)
++ mt7531_ind_c22_phy_write(sw_priv, phy, reg, value);
++ else
++ mt7531_ind_c45_phy_write(sw_priv, phy, devad, reg, value);
++ } else
++ mt7530_write(sw_priv, reg, value);
++
++ ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_REG, reg);
++ if (ret < 0)
++ goto err;
++
++ ret = nla_put_s32(rep_skb, MT7530_ATTR_TYPE_VAL, value);
++ if (ret < 0)
++ goto err;
++
++ return mt7530_nl_send_reply(rep_skb, info);
++
++err:
++ if (rep_skb)
++ nlmsg_free(rep_skb);
++
++ return ret;
++}
++
++static const enum mt7530_attr mt7530_nl_cmd_read_attrs[] = {
++ MT7530_ATTR_TYPE_REG
++};
++
++static const enum mt7530_attr mt7530_nl_cmd_write_attrs[] = {
++ MT7530_ATTR_TYPE_REG,
++ MT7530_ATTR_TYPE_VAL
++};
++
++static const struct mt7530_nl_cmd_item mt7530_nl_cmds[] = {
++ {
++ .cmd = MT7530_CMD_READ,
++ .require_dev = true,
++ .process = mt7530_nl_reply_read,
++ .required_attrs = mt7530_nl_cmd_read_attrs,
++ .nr_required_attrs = ARRAY_SIZE(mt7530_nl_cmd_read_attrs),
++ }, {
++ .cmd = MT7530_CMD_WRITE,
++ .require_dev = true,
++ .process = mt7530_nl_reply_write,
++ .required_attrs = mt7530_nl_cmd_write_attrs,
++ .nr_required_attrs = ARRAY_SIZE(mt7530_nl_cmd_write_attrs),
++ }
++};
++
++static int mt7530_nl_response(struct sk_buff *skb, struct genl_info *info)
++{
++ struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
++ const struct mt7530_nl_cmd_item *cmditem = NULL;
++ u32 sat_req_attrs = 0;
++ int i, ret;
++
++ for (i = 0; i < ARRAY_SIZE(mt7530_nl_cmds); i++) {
++ if (hdr->cmd == mt7530_nl_cmds[i].cmd) {
++ cmditem = &mt7530_nl_cmds[i];
++ break;
++ }
++ }
++
++ if (!cmditem) {
++ pr_info("mt7530-nl: unknown cmd %u\n", hdr->cmd);
++ return -EINVAL;
++ }
++
++ for (i = 0; i < cmditem->nr_required_attrs; i++) {
++ if (info->attrs[cmditem->required_attrs[i]])
++ sat_req_attrs++;
++ }
++
++ if (sat_req_attrs != cmditem->nr_required_attrs) {
++ pr_info("mt7530-nl: missing required attr(s) for cmd %u\n",
++ hdr->cmd);
++ return -EINVAL;
++ }
++
++ ret = cmditem->process(info);
++
++ mt7530_put();
++
++ return ret;
++}
++
++int mt7530_nl_init(struct mt7530_priv **priv)
++{
++ int ret;
++
++ pr_info("mt7530-nl: genl_register_family_with_ops \n");
++
++ sw_priv = *priv;
++ ret = genl_register_family(&mt7530_nl_family);
++ if (ret) {
++ return ret;
++ }
++
++ return 0;
++}
++
++void mt7530_nl_exit()
++{
++ sw_priv = NULL;
++ genl_unregister_family(&mt7530_nl_family);
++}
+Index: linux-5.4.203/drivers/net/dsa/mt7530_nl.h
+===================================================================
+--- /dev/null
++++ linux-5.4.203/drivers/net/dsa/mt7530_nl.h
+@@ -0,0 +1,49 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (c) 2018 MediaTek Inc.
++ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
++ */
++
++#ifndef _MT753x_NL_H_
++#define _MT753x_NL_H_
++
++#define MT7530_DSA_GENL_NAME "mt753x_dsa"
++#define MT7530_GENL_VERSION 0x1
++
++enum mt7530_cmd {
++ MT7530_CMD_UNSPEC = 0,
++ MT7530_CMD_REQUEST,
++ MT7530_CMD_REPLY,
++ MT7530_CMD_READ,
++ MT7530_CMD_WRITE,
++
++ __MT7530_CMD_MAX,
++};
++
++enum mt7530_attr {
++ MT7530_ATTR_TYPE_UNSPEC = 0,
++ MT7530_ATTR_TYPE_MESG,
++ MT7530_ATTR_TYPE_PHY,
++ MT7530_ATTR_TYPE_DEVAD,
++ MT7530_ATTR_TYPE_REG,
++ MT7530_ATTR_TYPE_VAL,
++ MT7530_ATTR_TYPE_DEV_NAME,
++ MT7530_ATTR_TYPE_DEV_ID,
++
++ __MT7530_ATTR_TYPE_MAX,
++};
++
++#define MT7530_NR_ATTR_TYPE (__MT7530_ATTR_TYPE_MAX - 1)
++
++struct mt7530_info {
++ struct mii_bus *bus;
++ void __iomem *base;
++ int direct_access;
++};
++
++#ifdef __KERNEL__
++int mt7530_nl_init(struct mt7530_priv **priv);
++void mt7530_nl_exit(void);
++#endif /* __KERNEL__ */
++
++#endif /* _MT7530_NL_H_ */
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/749-net-dsa-support-mt7988.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/749-net-dsa-support-mt7988.patch
new file mode 100644
index 0000000..7c468d8
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/749-net-dsa-support-mt7988.patch
@@ -0,0 +1,360 @@
+Index: linux-5.4.203/drivers/net/dsa/mt7530.c
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/mt7530.c
++++ linux-5.4.203/drivers/net/dsa/mt7530.c
+@@ -19,6 +19,7 @@
+ #include <linux/reset.h>
+ #include <linux/gpio/consumer.h>
+ #include <net/dsa.h>
++#include <linux/of_address.h>
+
+ #include "mt7530.h"
+ #include "mt7530_nl.h"
+@@ -170,28 +171,44 @@ core_clear(struct mt7530_priv *priv, u32
+ core_rmw(priv, reg, val, 0);
+ }
+
++static void
++mtk_w32(struct mt7530_priv *priv, u32 val, unsigned reg)
++{
++ __raw_writel(val, priv->base + reg);
++}
++
++static u32
++mtk_r32(struct mt7530_priv *priv, unsigned reg)
++{
++ return __raw_readl(priv->base + reg);
++}
++
+ static int
+ mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val)
+ {
+ struct mii_bus *bus = priv->bus;
+ u16 page, r, lo, hi;
+- int ret;
+-
+- page = (reg >> 6) & 0x3ff;
+- r = (reg >> 2) & 0xf;
+- lo = val & 0xffff;
+- hi = val >> 16;
+-
+- /* MT7530 uses 31 as the pseudo port */
+- ret = bus->write(bus, 0x1f, 0x1f, page);
+- if (ret < 0)
+- goto err;
++ int ret = 0;
+
+- ret = bus->write(bus, 0x1f, r, lo);
+- if (ret < 0)
+- goto err;
++ if (priv->direct_access){
++ mtk_w32(priv, val, reg);
++ } else {
++ page = (reg >> 6) & 0x3ff;
++ r = (reg >> 2) & 0xf;
++ lo = val & 0xffff;
++ hi = val >> 16;
++
++ /* MT7530 uses 31 as the pseudo port */
++ ret = bus->write(bus, 0x1f, 0x1f, page);
++ if (ret < 0)
++ goto err;
++
++ ret = bus->write(bus, 0x1f, r, lo);
++ if (ret < 0)
++ goto err;
+
+- ret = bus->write(bus, 0x1f, 0x10, hi);
++ ret = bus->write(bus, 0x1f, 0x10, hi);
++ }
+ err:
+ if (ret < 0)
+ dev_err(&bus->dev,
+@@ -206,21 +223,25 @@ mt7530_mii_read(struct mt7530_priv *priv
+ u16 page, r, lo, hi;
+ int ret;
+
+- page = (reg >> 6) & 0x3ff;
+- r = (reg >> 2) & 0xf;
++ if (priv->direct_access){
++ return mtk_r32(priv, reg);
++ } else {
++ page = (reg >> 6) & 0x3ff;
++ r = (reg >> 2) & 0xf;
+
+- /* MT7530 uses 31 as the pseudo port */
+- ret = bus->write(bus, 0x1f, 0x1f, page);
+- if (ret < 0) {
+- dev_err(&bus->dev,
+- "failed to read mt7530 register\n");
+- return ret;
+- }
++ /* MT7530 uses 31 as the pseudo port */
++ ret = bus->write(bus, 0x1f, 0x1f, page);
++ if (ret < 0) {
++ dev_err(&bus->dev,
++ "failed to read mt7530 register\n");
++ return ret;
++ }
+
+- lo = bus->read(bus, 0x1f, r);
+- hi = bus->read(bus, 0x1f, 0x10);
++ lo = bus->read(bus, 0x1f, r);
++ hi = bus->read(bus, 0x1f, 0x10);
+
+- return (hi << 16) | (lo & 0xffff);
++ return (hi << 16) | (lo & 0xffff);
++ }
+ }
+
+ void
+@@ -1906,9 +1927,9 @@ mt7531_phy_supported(struct dsa_switch *
+ if (mt7531_is_rgmii_port(priv, port))
+ return phy_interface_mode_is_rgmii(state->interface);
+ fallthrough;
+- case 6: /* 1st cpu port supports sgmii/8023z only */
+- if (state->interface != PHY_INTERFACE_MODE_SGMII &&
+- !phy_interface_mode_is_8023z(state->interface))
++ case 6: /* 1st cpu port supports sgmii/8023z/usxgmii/10gkr */
++ if (state->interface != PHY_INTERFACE_MODE_SGMII && state->interface != PHY_INTERFACE_MODE_USXGMII &&
++ state->interface != PHY_INTERFACE_MODE_10GKR && !phy_interface_mode_is_8023z(state->interface))
+ goto unsupported;
+ break;
+ default:
+@@ -2017,6 +2038,13 @@ static void mt7531_sgmii_validate(struct
+ phylink_set(supported, 1000baseX_Full);
+ phylink_set(supported, 2500baseX_Full);
+ phylink_set(supported, 2500baseT_Full);
++ phylink_set(supported, 10000baseKR_Full);
++ phylink_set(supported, 10000baseT_Full);
++ phylink_set(supported, 10000baseCR_Full);
++ phylink_set(supported, 10000baseSR_Full);
++ phylink_set(supported, 10000baseLR_Full);
++ phylink_set(supported, 10000baseLRM_Full);
++ phylink_set(supported, 10000baseER_Full);
+ }
+ }
+
+@@ -2165,6 +2193,8 @@ mt7531_mac_config(struct dsa_switch *ds,
+ case PHY_INTERFACE_MODE_NA:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ case PHY_INTERFACE_MODE_2500BASEX:
++ case PHY_INTERFACE_MODE_USXGMII:
++ case PHY_INTERFACE_MODE_10GKR:
+ if (phylink_autoneg_inband(mode))
+ return -EINVAL;
+
+@@ -2302,8 +2332,8 @@ static void mt753x_phylink_mac_link_up(s
+ /* MT753x MAC works in 1G full duplex mode for all up-clocked
+ * variants.
+ */
+- if (interface == PHY_INTERFACE_MODE_TRGMII ||
+- (phy_interface_mode_is_8023z(interface))) {
++ if (interface == PHY_INTERFACE_MODE_TRGMII || interface == PHY_INTERFACE_MODE_USXGMII ||
++ interface == PHY_INTERFACE_MODE_10GKR || (phy_interface_mode_is_8023z(interface))) {
+ speed = SPEED_1000;
+ duplex = DUPLEX_FULL;
+ }
+@@ -2402,8 +2432,8 @@ mt753x_phylink_validate(struct dsa_switc
+
+ phylink_set_port_modes(mask);
+
+- if (state->interface != PHY_INTERFACE_MODE_TRGMII ||
+- !phy_interface_mode_is_8023z(state->interface)) {
++ if (state->interface != PHY_INTERFACE_MODE_TRGMII || state->interface != PHY_INTERFACE_MODE_USXGMII ||
++ state->interface != PHY_INTERFACE_MODE_10GKR || !phy_interface_mode_is_8023z(state->interface)) {
+ phylink_set(mask, 10baseT_Half);
+ phylink_set(mask, 10baseT_Full);
+ phylink_set(mask, 100baseT_Half);
+@@ -2607,6 +2637,66 @@ mt753x_phy_write(struct dsa_switch *ds,
+ return priv->info->phy_write(ds, port, regnum, val);
+ }
+
++static int
++mt7988_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
++{
++ return 0;
++}
++
++static int
++mt7988_setup(struct dsa_switch *ds)
++{
++ struct mt7530_priv *priv = ds->priv;
++ u32 unused_pm = 0;
++ int ret, i;
++
++ /* Reset the switch through internal reset */
++ mt7530_write(priv, MT7530_SYS_CTRL,
++ SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST);
++
++ /* BPDU to CPU port */
++ mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK,
++ BIT(MT7530_CPU_PORT));
++ mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
++ MT753X_BPDU_CPU_ONLY);
++
++ /* Enable and reset MIB counters */
++ mt7530_mib_reset(ds);
++
++ for (i = 0; i < MT7530_NUM_PORTS; i++) {
++ /* Disable forwarding by default on all ports */
++ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
++ PCR_MATRIX_CLR);
++
++ mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR);
++
++ if (dsa_is_unused_port(ds, i))
++ unused_pm |= BIT(i);
++ else if (dsa_is_cpu_port(ds, i))
++ mt753x_cpu_port_enable(ds, i);
++ else
++ mt7530_port_disable(ds, i);
++
++ /* Enable consistent egress tag */
++ mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK,
++ PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
++ }
++
++ mt7531_phy_setup(ds);
++
++ /* Group and enable unused ports as a standalone dumb switch. */
++ setup_unused_ports(ds, unused_pm);
++
++ ds->configure_vlan_while_not_filtering = true;
++
++ /* Flush the FDB table */
++ ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);
++ if (ret < 0)
++ return ret;
++
++ return 0;
++}
++
+ static const struct dsa_switch_ops mt7530_switch_ops = {
+ .get_tag_protocol = mtk_get_tag_protocol,
+ .setup = mt753x_setup,
+@@ -2676,12 +2766,28 @@ static const struct mt753x_info mt753x_t
+ .mac_pcs_an_restart = mt7531_sgmii_restart_an,
+ .mac_pcs_link_up = mt7531_sgmii_link_up_force,
+ },
++ [ID_MT7988] = {
++ .id = ID_MT7988,
++ .sw_setup = mt7988_setup,
++ .phy_read = mt7531_ind_phy_read,
++ .phy_write = mt7531_ind_phy_write,
++ .pad_setup = mt7988_pad_setup,
++ .cpu_port_config = mt7531_cpu_port_config,
++ .phy_mode_supported = mt7531_phy_supported,
++ .mac_port_validate = mt7531_mac_port_validate,
++ .mac_port_get_state = mt7531_phylink_mac_link_state,
++ .mac_port_config = mt7531_mac_config,
++ .mac_pcs_an_restart = mt7531_sgmii_restart_an,
++ .mac_pcs_link_up = mt7531_sgmii_link_up_force,
++ },
++
+ };
+
+ static const struct of_device_id mt7530_of_match[] = {
+ { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
+ { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
+ { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], },
++ { .compatible = "mediatek,mt7988", .data = &mt753x_table[ID_MT7988], },
+ { /* sentinel */ },
+ };
+ MODULE_DEVICE_TABLE(of, mt7530_of_match);
+@@ -2691,6 +2797,7 @@ mt7530_probe(struct mdio_device *mdiodev
+ {
+ struct mt7530_priv *priv;
+ struct device_node *dn;
++ struct device_node *switch_node = NULL;
+ int ret;
+
+ dn = mdiodev->dev.of_node;
+@@ -2760,6 +2867,16 @@ mt7530_probe(struct mdio_device *mdiodev
+ }
+ }
+
++ switch_node = of_find_node_by_name(NULL, "switch0");
++ if(switch_node) {
++ priv->base = of_iomap(switch_node, 0);
++ if(priv->base == NULL){
++ dev_err(&mdiodev->dev, "of_iomap failed\n");
++ return -ENOMEM;
++ }
++ priv->direct_access = 1;
++ }
++
+ priv->bus = mdiodev->bus;
+ priv->dev = &mdiodev->dev;
+ priv->ds->priv = priv;
+@@ -2768,9 +2885,12 @@ mt7530_probe(struct mdio_device *mdiodev
+ dev_set_drvdata(&mdiodev->dev, priv);
+
+ ret = dsa_register_switch(priv->ds);
+- if (ret)
+- return ret;
+-
++ if (ret) {
++ if(priv->base)
++ iounmap(priv->base);
++
++ return ret;
++ }
+ mt7530_nl_init(&priv);
+
+ return 0;
+@@ -2795,6 +2915,9 @@ mt7530_remove(struct mdio_device *mdiode
+ dsa_unregister_switch(priv->ds);
+ mutex_destroy(&priv->reg_mutex);
+
++ if(priv->base)
++ iounmap(priv->base);
++
+ mt7530_nl_exit();
+ }
+
+Index: linux-5.4.203/drivers/net/dsa/mt7530.h
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/mt7530.h
++++ linux-5.4.203/drivers/net/dsa/mt7530.h
+@@ -16,6 +16,7 @@ enum mt753x_id {
+ ID_MT7530 = 0,
+ ID_MT7621 = 1,
+ ID_MT7531 = 2,
++ ID_MT7988 = 3,
+ };
+
+ #define NUM_TRGMII_CTRL 5
+@@ -51,11 +52,11 @@ enum mt753x_id {
+ #define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16)
+ #define MT7531_CPU_PMAP_MASK GENMASK(7, 0)
+
+-#define MT753X_MIRROR_REG(id) (((id) == ID_MT7531) ? \
++#define MT753X_MIRROR_REG(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
+ MT7531_CFC : MT7530_MFC)
+-#define MT753X_MIRROR_EN(id) (((id) == ID_MT7531) ? \
++#define MT753X_MIRROR_EN(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
+ MT7531_MIRROR_EN : MIRROR_EN)
+-#define MT753X_MIRROR_MASK(id) (((id) == ID_MT7531) ? \
++#define MT753X_MIRROR_MASK(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
+ MT7531_MIRROR_MASK : MIRROR_MASK)
+
+ /* Registers for BPDU and PAE frame control*/
+@@ -261,7 +262,7 @@ enum mt7530_vlan_port_attr {
+ MT7531_FORCE_DPX | \
+ MT7531_FORCE_RX_FC | \
+ MT7531_FORCE_TX_FC)
+-#define PMCR_FORCE_MODE_ID(id) (((id) == ID_MT7531) ? \
++#define PMCR_FORCE_MODE_ID(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
+ MT7531_FORCE_MODE : \
+ PMCR_FORCE_MODE)
+ #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \
+@@ -733,6 +734,8 @@ struct mt7530_priv {
+ struct regulator *core_pwr;
+ struct regulator *io_pwr;
+ struct gpio_desc *reset;
++ void __iomem *base;
++ int direct_access;
+ const struct mt753x_info *info;
+ unsigned int id;
+ bool mcm;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/750-add-mdio-bus-for-phy-node.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/750-add-mdio-bus-for-phy-node.patch
new file mode 100644
index 0000000..5a130b1
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/750-add-mdio-bus-for-phy-node.patch
@@ -0,0 +1,165 @@
+Index: linux-5.4.203/drivers/net/dsa/mt7530.c
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/mt7530.c
++++ linux-5.4.203/drivers/net/dsa/mt7530.c
+@@ -847,6 +847,132 @@ mt7531_ind_phy_write(struct dsa_switch *
+ return ret;
+ }
+
++static int mt753x_mdio_read(struct mii_bus *bus, int addr, int regnum)
++{
++ struct mt7530_priv *priv = bus->priv;
++ struct mt7530_dummy_poll p;
++ int ret;
++ u32 val;
++
++ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
++
++ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
++
++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
++ !(val & MT7531_PHY_ACS_ST), 20, 100000);
++ if (ret < 0) {
++ dev_err(priv->dev, "poll timeout\n");
++ goto out;
++ }
++
++ val = MT7531_MDIO_CL22_READ | MT7531_MDIO_PHY_ADDR(addr) |
++ MT7531_MDIO_REG_ADDR(regnum);
++
++ mt7530_mii_write(priv, MT7531_PHY_IAC, val | MT7531_PHY_ACS_ST);
++
++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
++ !(val & MT7531_PHY_ACS_ST), 20, 100000);
++ if (ret < 0) {
++ dev_err(priv->dev, "poll timeout\n");
++ goto out;
++ }
++
++ ret = val & MT7531_MDIO_RW_DATA_MASK;
++out:
++ mutex_unlock(&priv->bus->mdio_lock);
++
++ return ret;
++}
++
++static int mt753x_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
++{
++ struct mt7530_priv *priv = bus->priv;
++ struct mt7530_dummy_poll p;
++ int ret;
++ u32 reg;
++
++ INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
++
++ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
++
++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,
++ !(reg & MT7531_PHY_ACS_ST), 20, 100000);
++ if (ret < 0) {
++ dev_err(priv->dev, "poll timeout\n");
++ goto out;
++ }
++
++ reg = MT7531_MDIO_CL22_WRITE | MT7531_MDIO_PHY_ADDR(addr) |
++ MT7531_MDIO_REG_ADDR(regnum) | val;
++
++ mt7530_mii_write(priv, MT7531_PHY_IAC, reg | MT7531_PHY_ACS_ST);
++
++ ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,
++ !(reg & MT7531_PHY_ACS_ST), 20, 100000);
++ if (ret < 0) {
++ dev_err(priv->dev, "poll timeout\n");
++ goto out;
++ }
++
++out:
++ mutex_unlock(&priv->bus->mdio_lock);
++
++ return ret;
++}
++
++static int mt753x_mdio_init(struct mt7530_priv *priv)
++{
++ struct device_node *dn;
++ struct device_node *mii_np;
++ int ret;
++
++ dn = priv->dev->of_node;
++
++ mii_np = of_get_child_by_name(dn, "mdio-bus");
++ if (!mii_np) {
++ ret = -ENODEV;
++ goto err_put_node;
++ }
++
++ if (!of_device_is_available(mii_np)) {
++ ret = -ENODEV;
++ goto err_put_node;
++ }
++
++ priv->gbus = devm_mdiobus_alloc(priv->dev);
++ if (!priv->gbus) {
++ ret = -ENOMEM;
++ goto err_put_node;
++ }
++ priv->gbus->name = "mt753x_mdio";
++ priv->gbus->read = mt753x_mdio_read;
++ priv->gbus->write = mt753x_mdio_write;
++ priv->gbus->priv = priv;
++ priv->gbus->parent = priv->dev;
++
++ if(snprintf(priv->gbus->id, MII_BUS_ID_SIZE, "%s@%s", mii_np->name, dn->name) < 0) {
++ ret = -ENOMEM;
++ goto err_put_node;
++ }
++
++ ret = of_mdiobus_register(priv->gbus, mii_np);
++ if (ret)
++ priv->gbus = NULL;
++
++err_put_node:
++ of_node_put(mii_np);
++
++ return ret;
++}
++
++static void mt753x_mdio_exit(struct mt7530_priv *priv)
++{
++ if (!priv->gbus)
++ return;
++
++ mdiobus_unregister(priv->gbus);
++}
++
+ static void
+ mt7530_get_strings(struct dsa_switch *ds, int port, u32 stringset,
+ uint8_t *data)
+@@ -2892,6 +3018,7 @@ mt7530_probe(struct mdio_device *mdiodev
+ return ret;
+ }
+ mt7530_nl_init(&priv);
++ mt753x_mdio_init(priv);
+
+ return 0;
+ }
+@@ -2919,6 +3046,7 @@ mt7530_remove(struct mdio_device *mdiode
+ iounmap(priv->base);
+
+ mt7530_nl_exit();
++ mt753x_mdio_exit(priv);
+ }
+
+ static struct mdio_driver mt7530_mdio_driver = {
+Index: linux-5.4.203/drivers/net/dsa/mt7530.h
+===================================================================
+--- linux-5.4.203.orig/drivers/net/dsa/mt7530.h
++++ linux-5.4.203/drivers/net/dsa/mt7530.h
+@@ -730,6 +730,7 @@ struct mt7530_priv {
+ struct device *dev;
+ struct dsa_switch *ds;
+ struct mii_bus *bus;
++ struct mii_bus *gbus;
+ struct reset_control *rstc;
+ struct regulator *core_pwr;
+ struct regulator *io_pwr;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
new file mode 100644
index 0000000..c20e930
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch
@@ -0,0 +1,142 @@
+diff --git a/drivers/phy/mediatek/phy-mtk-xsphy.c b/drivers/phy/mediatek/phy-mtk-xsphy.c
+index 8c51131..e77092c 100644
+--- a/drivers/phy/mediatek/phy-mtk-xsphy.c
++++ b/drivers/phy/mediatek/phy-mtk-xsphy.c
+@@ -12,10 +12,12 @@
+ #include <linux/delay.h>
+ #include <linux/io.h>
+ #include <linux/iopoll.h>
++#include <linux/mfd/syscon.h>
+ #include <linux/module.h>
+ #include <linux/of_address.h>
+ #include <linux/phy/phy.h>
+ #include <linux/platform_device.h>
++#include <linux/regmap.h>
+
+ /* u2 phy banks */
+ #define SSUSB_SIFSLV_MISC 0x000
+@@ -88,12 +90,22 @@
+ #define XSP_SR_COEF_DIVISOR 1000
+ #define XSP_FM_DET_CYCLE_CNT 1024
+
++/* PHY switch between pcie/usb3/sgmii */
++#define USB_PHY_SWITCH_CTRL 0x0
++#define RG_PHY_SW_TYPE GENMASK(3, 0)
++#define RG_PHY_SW_PCIE 0x0
++#define RG_PHY_SW_USB3 0x1
++#define RG_PHY_SW_SGMII 0x2
++
+ struct xsphy_instance {
+ struct phy *phy;
+ void __iomem *port_base;
+ struct clk *ref_clk; /* reference clock of anolog phy */
+ u32 index;
+ u32 type;
++ struct regmap *type_sw;
++ u32 type_sw_reg;
++ u32 type_sw_index;
+ /* only for HQA test */
+ int efuse_intr;
+ int efuse_tx_imp;
+@@ -365,6 +377,62 @@ static void u3_phy_props_set(struct mtk_xsphy *xsphy,
+ }
+ }
+
++/* type switch for usb3/pcie/sgmii */
++static int phy_type_syscon_get(struct xsphy_instance *instance,
++ struct device_node *dn)
++{
++ struct of_phandle_args args;
++ int ret;
++
++ /* type switch function is optional */
++ if (!of_property_read_bool(dn, "mediatek,syscon-type"))
++ return 0;
++
++ ret = of_parse_phandle_with_fixed_args(dn, "mediatek,syscon-type",
++ 2, 0, &args);
++ if (ret)
++ return ret;
++
++ instance->type_sw_reg = args.args[0];
++ instance->type_sw_index = args.args[1] & 0x3; /* <=3 */
++ instance->type_sw = syscon_node_to_regmap(args.np);
++ of_node_put(args.np);
++ dev_info(&instance->phy->dev, "type_sw - reg %#x, index %d\n",
++ instance->type_sw_reg, instance->type_sw_index);
++
++ return PTR_ERR_OR_ZERO(instance->type_sw);
++}
++
++static int phy_type_set(struct xsphy_instance *instance)
++{
++ int type;
++ u32 offset;
++
++ if (!instance->type_sw)
++ return 0;
++
++ switch (instance->type) {
++ case PHY_TYPE_USB3:
++ type = RG_PHY_SW_USB3;
++ break;
++ case PHY_TYPE_PCIE:
++ type = RG_PHY_SW_PCIE;
++ break;
++ case PHY_TYPE_SGMII:
++ type = RG_PHY_SW_SGMII;
++ break;
++ case PHY_TYPE_USB2:
++ default:
++ return 0;
++ }
++
++ offset = instance->type_sw_index * BITS_PER_BYTE;
++ regmap_update_bits(instance->type_sw, instance->type_sw_reg,
++ RG_PHY_SW_TYPE << offset, type << offset);
++
++ return 0;
++}
++
+ static int mtk_phy_init(struct phy *phy)
+ {
+ struct xsphy_instance *inst = phy_get_drvdata(phy);
+@@ -385,6 +453,10 @@ static int mtk_phy_init(struct phy *phy)
+ case PHY_TYPE_USB3:
+ u3_phy_props_set(xsphy, inst);
+ break;
++ case PHY_TYPE_PCIE:
++ case PHY_TYPE_SGMII:
++ /* nothing to do, only used to set type */
++ break;
+ default:
+ dev_err(xsphy->dev, "incompatible phy type\n");
+ clk_disable_unprepare(inst->ref_clk);
+@@ -463,12 +535,15 @@ static struct phy *mtk_phy_xlate(struct device *dev,
+
+ inst->type = args->args[0];
+ if (!(inst->type == PHY_TYPE_USB2 ||
+- inst->type == PHY_TYPE_USB3)) {
++ inst->type == PHY_TYPE_USB3 ||
++ inst->type == PHY_TYPE_PCIE ||
++ inst->type == PHY_TYPE_SGMII)) {
+ dev_err(dev, "unsupported phy type: %d\n", inst->type);
+ return ERR_PTR(-EINVAL);
+ }
+
+ phy_parse_property(xsphy, inst);
++ phy_type_set(inst);
+
+ return inst->phy;
+ }
+@@ -575,6 +650,10 @@ static int mtk_xsphy_probe(struct platform_device *pdev)
+ retval = PTR_ERR(inst->ref_clk);
+ goto put_child;
+ }
++
++ retval = phy_type_syscon_get(inst, child_np);
++ if (retval)
++ goto put_child;
+ }
+
+ provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9000-PATCH-1-1-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9000-PATCH-1-1-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch
new file mode 100644
index 0000000..e82e1bc
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/9000-PATCH-1-1-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch
@@ -0,0 +1,57 @@
+From 5f8c12ffa661e3707790f59827a45ff4102f2886 Mon Sep 17 00:00:00 2001
+From: Zhanyong Wang <zhanyong.wang@mediatek.com>
+Date: Mon, 15 Aug 2022 14:13:50 +0800
+Subject: [PATCH] xHCI: change compliance mode de-emphasis default as gen1
+
+Port0 is using Gen2 Phy for 10GHz, and Port0 is running
+on 5GHz actually. hence to change compliance mode de-
+emphasis default as Gen1.
+
+Signed-off-by: Zhanyong Wang <zhanyong.wang@mediatek.com>
+---
+ drivers/usb/host/xhci-mtk.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
+index 2a4b73a658f9..b1201fb65fd6 100644
+--- a/drivers/usb/host/xhci-mtk.c
++++ b/drivers/usb/host/xhci-mtk.c
+@@ -24,6 +24,11 @@
+ #include "xhci-mtk.h"
+ #include "xhci-mtk-test.h"
+
++/* COMPLIANCE_CP5_CP7_TXDEEMPH_10G register */
++#define COMPLIANCE_CP5_CP7_TXDEEMPH_10G 0x2428
++#define CP5_CP7_TXDEEMPH_10G GENMASK(17, 0)
++#define CP5_CP7_TXDEEMPH_10G_VAL(val) ((val) & 0x03FFFF)
++
+ /* ip_pw_ctrl0 register */
+ #define CTRL0_IP_SW_RST BIT(0)
+
+@@ -415,6 +420,7 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
+ {
+ struct xhci_hcd_mtk *mtk = hcd_to_mtk(hcd);
+ int ret;
++ u32 val;
+
+ if (usb_hcd_is_primary_hcd(hcd)) {
+ ret = xhci_mtk_ssusb_config(mtk);
+@@ -432,6 +438,15 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
+ return ret;
+ }
+
++ /* change COMPLIANCE_CP5_CP7_TXDEEMPH_10G as Gen1 instead Gen2 */
++ if (hcd->rsrc_start == 0x11190000ULL) {
++ val = readl(mtk->hcd->regs + COMPLIANCE_CP5_CP7_TXDEEMPH_10G);
++ val &= ~CP5_CP7_TXDEEMPH_10G;
++ val |= 0x00001;
++ val = CP5_CP7_TXDEEMPH_10G_VAL(val);
++ writel(val, mtk->hcd->regs + COMPLIANCE_CP5_CP7_TXDEEMPH_10G);
++ }
++
+ return ret;
+ }
+
+--
+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 2ad7eec..4c9012a 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
@@ -1,14 +1,21 @@
#patch patches-5.4 (come from openwrt/lede/target/linux/mediatek)
SRC_URI_append = " \
file://0001-clk-mtk-add-mt7986-support.patch \
+ file://0001-cpufreq-add-the-missing-platform-driver-unregister.patch \
file://0001-v5.7-spi-make-spi-max-frequency-optional.patch \
file://0002-clk-mtk-add-mt7981-support.patch \
+ file://0002-cpufreq-Enable-clocks-and-regulators.patch \
file://0002-v5.7-spi-add-support-for-mediatek-spi-nor-controller.patch \
+ file://0003-clk-mtk-add-mt7988-support.patch \
+ file://0003-cpufreq-add-mt7988a-spim-snand-support.patch \
file://0003-switch-add-mt7531.patch \
+ file://0005-clk-mtk-add-chg-shift-control.patch \
file://0005-dts-mt7622-add-gsw.patch \
file://0005-dts-mt7629-add-gsw.patch \
file://0006-dts-fix-bpi2-console.patch \
file://0006-dts-fix-bpi64-console.patch \
+ file://0006-powerdomain-add-mt7988-support.patch \
+ file://0007-cpufreq-mtk-vbining-add-mt7988-support.patch \
file://0010-dts-mt7629-rfb-fix-firmware-partition.patch \
file://0020-dts-mt7622-enable-new-mtk-snand-for-ubi.patch \
file://0021-dts-mt7622-remove-cooling-device.patch \
@@ -54,6 +61,8 @@
file://0901-i2c-busses-add-mt7981-support.patch \
file://0930-pwm-add-mt7986-support.patch \
file://0931-pwm-add-mt7981-support.patch \
+ file://0932-add-pwm-feature-in-mt7988-project.patch \
+ file://0950-add-pmic-config.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 \
@@ -69,15 +78,18 @@
file://1023-kgdb-add-interrupt-control.patch \
file://1024-pcie-add-multi-MSI-support.patch \
file://1661-Add-trngv2-driver-support.patch \
+ file://1662-trng-Add-trng-support-for-mt7988.patch \
file://2000-misc-add-mtk-platform.patch \
file://400-mtd-add-mtk-snand-driver.patch \
file://401-pinctrl-add-mt7986-driver.patch \
+ file://401-pinctrl-enable-mt7988-pinctrl-config.patch \
file://402-pinctrl-add-mt7981-driver.patch \
file://412-mtd-spinand-gigadevice-Add-support-for-F50L1G41LB-and-GD5F1GQ5UExxG.patch \
file://413-mtd-spinand-gigadevice-Add-support-for-GD5FxGQxUExxG-GD5FxGQxUExxH-and-GD5FxGMxUExxG-series.patch \
file://414-mtd-spinand-fix-gigadevice-read-dummy.patch \
file://415-mtd-spinand-fix-F50L1G41LB-ecc-check.patch \
file://500-auxadc-add-auxadc-32k-clk.patch \
+ file://6001-mtk-thermal-add-lvts-support.patch \
file://7000-fix-race-inside-napi-enable.patch \
file://7001-net-make-napi-disable-symmetric-with-enable.patch \
file://7002-net-fix-premature-exit-from-napi-state-polling-in-napi-disable-v2.patch \
@@ -91,8 +103,12 @@
file://744-en8801s-gphy-support.patch \
file://745-en8801sc-gphy-support.patch \
file://745-mdiobus-add-c45.patch \
+ file://746-add-mediatek-2p5ge-phy-support.patch \
file://746-mxl-gpy-phy-support.patch \
file://747-net-phy-aquantia-add-AQR113C.patch \
+ file://748-add-netlink-support-for-dsa.patch \
+ file://749-net-dsa-support-mt7988.patch \
+ file://750-add-mdio-bus-for-phy-node.patch \
file://8000-PATCH-1-4-tphy-support-type-switch-by-pericfg.patch \
file://8001-PATCH-2-4-dt-bindings-phy-Add-PHY_TYPE_DP-definition.patch \
file://8002-PATCH-3-4-dt-bindings-phy-Add-PHY_TYPE_XPCS-definition.patch \
@@ -103,6 +119,8 @@
file://8007-phy-phy-mtk-tphy-Add-PCIe-2-lane-efuse-support.patch \
file://8008-phy-phy-mtk-tphy-add-auto-load-valid-check-mechanism.patch \
file://8010-ovs-support-flow-offload.patch \
+ file://8010-phy-phy-mtk-xsphy-support-type-switch-by-pericfg.patch \
+ file://9000-PATCH-1-1-xHCI-change-compliance-mode-de-emphasis-default-as-g.patch \
file://9001-PATCH-1-2-xHCI-MT7986-USB-2.0-USBIF-compliance-toolkit.patch \
file://9002-PATCH-1-1-usb-add-embedded-Host-feature-support.patch \
file://9009-Add-spi-runtime-PM-support.patch \