aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mediatek/patches-5.10
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2020-10-24 21:15:20 +0200
committerDaniel Golle <daniel@makrotopia.org>2021-02-28 00:45:56 +0000
commitc46ccb69d17e584479df849a107423175a143c83 (patch)
tree10c0b329ba571cbdd366e48e61173a64e56c841d /target/linux/mediatek/patches-5.10
parent11425c9de29c8b9c5e4d7eec163a6afbb7fbdce2 (diff)
downloadupstream-c46ccb69d17e584479df849a107423175a143c83.tar.gz
upstream-c46ccb69d17e584479df849a107423175a143c83.tar.bz2
upstream-c46ccb69d17e584479df849a107423175a143c83.zip
mediatek: mt7622: add Linux 5.10 support
Switch mt7622 subtarget to Linux 5.10, it has been tested by many of us on several devices for a couple of weeks already. Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'target/linux/mediatek/patches-5.10')
-rw-r--r--target/linux/mediatek/patches-5.10/100-dts-update-mt7622-rfb1.patch119
-rw-r--r--target/linux/mediatek/patches-5.10/101-dts-update-mt7629-rfb.patch37
-rw-r--r--target/linux/mediatek/patches-5.10/110-dts-fix-bpi2-console.patch10
-rw-r--r--target/linux/mediatek/patches-5.10/111-dts-fix-bpi64-console.patch11
-rw-r--r--target/linux/mediatek/patches-5.10/130-dts-mt7629-add-snand-support.patch97
-rw-r--r--target/linux/mediatek/patches-5.10/131-dts-mt7622-add-snand-support.patch96
-rw-r--r--target/linux/mediatek/patches-5.10/140-dts-fix-wmac-support-for-mt7622-rfb1.patch18
-rw-r--r--target/linux/mediatek/patches-5.10/150-dts-mt7623-eip97-inside-secure-support.patch23
-rw-r--r--target/linux/mediatek/patches-5.10/200-phy-phy-mtk-tphy-Add-hifsys-support.patch66
-rw-r--r--target/linux/mediatek/patches-5.10/300-mtd-mtk-ecc-move-mtk-ecc-header-file-to-include-mtd.patch139
-rw-r--r--target/linux/mediatek/patches-5.10/310-mtd-spinand-disable-on-die-ECC.patch31
-rw-r--r--target/linux/mediatek/patches-5.10/320-spi-spi-mem-MediaTek-Add-SPI-NAND-Flash-interface-dr.patch1246
-rw-r--r--target/linux/mediatek/patches-5.10/330-mtk-bmt-support.patch840
-rw-r--r--target/linux/mediatek/patches-5.10/400-crypto-add-eip97-inside-secure-support.patch27
-rw-r--r--target/linux/mediatek/patches-5.10/401-crypto-fix-eip97-cache-incoherent.patch26
-rw-r--r--target/linux/mediatek/patches-5.10/410-bt-mtk-serial-fix.patch33
-rw-r--r--target/linux/mediatek/patches-5.10/500-gsw-rtl8367s-mt7622-support.patch25
-rw-r--r--target/linux/mediatek/patches-5.10/600-dt-bindings-PCI-Mediatek-Update-PCIe-binding.patch415
-rw-r--r--target/linux/mediatek/patches-5.10/601-PCI-mediatek-Use-regmap-to-get-shared-pcie-cfg-base.patch217
-rw-r--r--target/linux/mediatek/patches-5.10/602-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-MT7622.patch417
-rw-r--r--target/linux/mediatek/patches-5.10/603-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch203
-rw-r--r--target/linux/mediatek/patches-5.10/610-pcie-mediatek-fix-clearing-interrupt-status.patch24
-rw-r--r--target/linux/mediatek/patches-5.10/700-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch85
-rw-r--r--target/linux/mediatek/patches-5.10/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch108
24 files changed, 4313 insertions, 0 deletions
diff --git a/target/linux/mediatek/patches-5.10/100-dts-update-mt7622-rfb1.patch b/target/linux/mediatek/patches-5.10/100-dts-update-mt7622-rfb1.patch
new file mode 100644
index 0000000000..f4e77cf69c
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/100-dts-update-mt7622-rfb1.patch
@@ -0,0 +1,119 @@
+--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+@@ -1,7 +1,6 @@
+ /*
+- * Copyright (c) 2017 MediaTek Inc.
+- * Author: Ming Huang <ming.huang@mediatek.com>
+- * Sean Wang <sean.wang@mediatek.com>
++ * Copyright (c) 2018 MediaTek Inc.
++ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ */
+@@ -23,7 +22,7 @@
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+- bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512";
++ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512";
+ };
+
+ cpus {
+@@ -40,23 +39,22 @@
+
+ gpio-keys {
+ compatible = "gpio-keys";
+- poll-interval = <100>;
+
+ factory {
+ label = "factory";
+ linux,code = <BTN_0>;
+- gpios = <&pio 0 0>;
++ gpios = <&pio 0 GPIO_ACTIVE_LOW>;
+ };
+
+ wps {
+ label = "wps";
+ linux,code = <KEY_WPS_BUTTON>;
+- gpios = <&pio 102 0>;
++ gpios = <&pio 102 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ memory {
+- reg = <0 0x40000000 0 0x20000000>;
++ reg = <0 0x40000000 0 0x40000000>;
+ };
+
+ reg_1p8v: regulator-1p8v {
+@@ -132,22 +130,22 @@
+
+ port@0 {
+ reg = <0>;
+- label = "lan0";
++ label = "lan1";
+ };
+
+ port@1 {
+ reg = <1>;
+- label = "lan1";
++ label = "lan2";
+ };
+
+ port@2 {
+ reg = <2>;
+- label = "lan2";
++ label = "lan3";
+ };
+
+ port@3 {
+ reg = <3>;
+- label = "lan3";
++ label = "lan4";
+ };
+
+ port@4 {
+@@ -236,15 +234,28 @@
+
+ &pcie {
+ pinctrl-names = "default";
+- pinctrl-0 = <&pcie0_pins>;
++ pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>;
+ status = "okay";
+
+ pcie@0,0 {
+ status = "okay";
+ };
++
++ pcie@1,0 {
++ status = "okay";
++ };
+ };
+
+ &pio {
++ /* Attention: GPIO 90 is used to switch between PCIe@1,0 and
++ * SATA functions. i.e. output-high: PCIe, output-low: SATA
++ */
++ asm_sel {
++ gpio-hog;
++ gpios = <90 GPIO_ACTIVE_HIGH>;
++ output-high;
++ };
++
+ /* eMMC is shared pin with parallel NAND */
+ emmc_pins_default: emmc-pins-default {
+ mux {
+@@ -511,11 +522,11 @@
+ };
+
+ &sata {
+- status = "okay";
++ status = "disabled";
+ };
+
+ &sata_phy {
+- status = "okay";
++ status = "disabled";
+ };
+
+ &spi0 {
diff --git a/target/linux/mediatek/patches-5.10/101-dts-update-mt7629-rfb.patch b/target/linux/mediatek/patches-5.10/101-dts-update-mt7629-rfb.patch
new file mode 100644
index 0000000000..8d3e283315
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/101-dts-update-mt7629-rfb.patch
@@ -0,0 +1,37 @@
+--- a/arch/arm/boot/dts/mt7629-rfb.dts
++++ b/arch/arm/boot/dts/mt7629-rfb.dts
+@@ -18,6 +18,7 @@
+
+ chosen {
+ stdout-path = "serial0:115200n8";
++ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8";
+ };
+
+ gpio-keys {
+@@ -69,6 +70,7 @@
+ gmac0: mac@0 {
+ compatible = "mediatek,eth-mac";
+ reg = <0>;
++ mtd-mac-address = <&factory 0x2a>;
+ phy-mode = "2500base-x";
+ fixed-link {
+ speed = <2500>;
+@@ -80,6 +82,7 @@
+ gmac1: mac@1 {
+ compatible = "mediatek,eth-mac";
+ reg = <1>;
++ mtd-mac-address = <&factory 0x24>;
+ phy-mode = "gmii";
+ phy-handle = <&phy0>;
+ };
+@@ -133,8 +136,9 @@
+ };
+
+ partition@b0000 {
+- label = "kernel";
++ label = "firmware";
+ reg = <0xb0000 0xb50000>;
++ compatible = "denx,fit";
+ };
+ };
+ };
diff --git a/target/linux/mediatek/patches-5.10/110-dts-fix-bpi2-console.patch b/target/linux/mediatek/patches-5.10/110-dts-fix-bpi2-console.patch
new file mode 100644
index 0000000000..c696e7d369
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/110-dts-fix-bpi2-console.patch
@@ -0,0 +1,10 @@
+--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
++++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
+@@ -19,6 +19,7 @@
+
+ chosen {
+ stdout-path = "serial2:115200n8";
++ bootargs = "console=ttyS2,115200n8";
+ };
+
+ connector {
diff --git a/target/linux/mediatek/patches-5.10/111-dts-fix-bpi64-console.patch b/target/linux/mediatek/patches-5.10/111-dts-fix-bpi64-console.patch
new file mode 100644
index 0000000000..07a2eae245
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/111-dts-fix-bpi64-console.patch
@@ -0,0 +1,11 @@
+--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
+@@ -22,7 +22,7 @@
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+- bootargs = "earlycon=uart8250,mmio32,0x11002000 swiotlb=512";
++ bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512";
+ };
+
+ cpus {
diff --git a/target/linux/mediatek/patches-5.10/130-dts-mt7629-add-snand-support.patch b/target/linux/mediatek/patches-5.10/130-dts-mt7629-add-snand-support.patch
new file mode 100644
index 0000000000..479694b400
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/130-dts-mt7629-add-snand-support.patch
@@ -0,0 +1,97 @@
+From c813fbe806257c574240770ef716fbee19f7dbfa Mon Sep 17 00:00:00 2001
+From: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+Date: Thu, 6 Jun 2019 16:29:04 +0800
+Subject: [PATCH] spi: spi-mem: Mediatek: Add SPI Nand support for MT7629
+
+Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+---
+ arch/arm/boot/dts/mt7629-rfb.dts | 45 ++++++++++++++++++++++++++++++++
+ arch/arm/boot/dts/mt7629.dtsi | 22 ++++++++++++++++
+ 3 files changed, 79 insertions(+)
+
+--- a/arch/arm/boot/dts/mt7629.dtsi
++++ b/arch/arm/boot/dts/mt7629.dtsi
+@@ -272,6 +272,28 @@
+ status = "disabled";
+ };
+
++ bch: ecc@1100e000 {
++ compatible = "mediatek,mt7622-ecc";
++ reg = <0x1100e000 0x1000>;
++ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg CLK_PERI_NFIECC_PD>;
++ clock-names = "nfiecc_clk";
++ status = "disabled";
++ };
++
++ snfi: spi@1100d000 {
++ compatible = "mediatek,mt7629-snfi";
++ reg = <0x1100d000 0x1000>;
++ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg CLK_PERI_NFI_PD>,
++ <&pericfg CLK_PERI_SNFI_PD>;
++ clock-names = "nfi_clk", "spi_clk";
++ ecc-engine = <&bch>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "disabled";
++ };
++
+ spi: spi@1100a000 {
+ compatible = "mediatek,mt7629-spi",
+ "mediatek,mt7622-spi";
+--- a/arch/arm/boot/dts/mt7629-rfb.dts
++++ b/arch/arm/boot/dts/mt7629-rfb.dts
+@@ -249,6 +249,52 @@
+ };
+ };
+
++&bch {
++ status = "okay";
++};
++
++&snfi {
++ pinctrl-names = "default";
++ pinctrl-0 = <&serial_nand_pins>;
++ status = "okay";
++
++ spi_nand@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "spi-nand";
++ spi-max-frequency = <104000000>;
++ reg = <0>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ label = "Bootloader";
++ reg = <0x00000 0x0100000>;
++ read-only;
++ };
++
++ partition@100000 {
++ label = "Config";
++ reg = <0x100000 0x0040000>;
++ };
++
++ partition@140000 {
++ label = "factory";
++ reg = <0x140000 0x0080000>;
++ };
++
++ partition@1c0000 {
++ label = "firmware";
++ reg = <0x1c0000 0x1000000>;
++ };
++
++ };
++ };
++};
++
+ &spi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_pins>;
diff --git a/target/linux/mediatek/patches-5.10/131-dts-mt7622-add-snand-support.patch b/target/linux/mediatek/patches-5.10/131-dts-mt7622-add-snand-support.patch
new file mode 100644
index 0000000000..de96162e8a
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/131-dts-mt7622-add-snand-support.patch
@@ -0,0 +1,96 @@
+--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+@@ -554,6 +554,19 @@
+ status = "disabled";
+ };
+
++ snfi: spi@1100d000 {
++ compatible = "mediatek,mt7622-snfi";
++ reg = <0 0x1100d000 0 0x1000>;
++ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
++ clocks = <&pericfg CLK_PERI_NFI_PD>,
++ <&pericfg CLK_PERI_SNFI_PD>;
++ clock-names = "nfi_clk", "spi_clk";
++ ecc-engine = <&bch>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "disabled";
++ };
++
+ nor_flash: spi@11014000 {
+ compatible = "mediatek,mt7622-nor",
+ "mediatek,mt8173-nor";
+--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+@@ -85,7 +85,7 @@
+ };
+
+ &bch {
+- status = "disabled";
++ status = "okay";
+ };
+
+ &btif {
+@@ -529,6 +529,62 @@
+ status = "disabled";
+ };
+
++&snfi {
++ pinctrl-names = "default";
++ pinctrl-0 = <&serial_nand_pins>;
++ status = "okay";
++
++ spi_nand@0 {
++ #address-cells = <1>;
++ #size-cells = <1>;
++ compatible = "spi-nand";
++ spi-max-frequency = <104000000>;
++ reg = <0>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ label = "Preloader";
++ reg = <0x00000 0x0080000>;
++ read-only;
++ };
++
++ partition@80000 {
++ label = "ATF";
++ reg = <0x80000 0x0040000>;
++ };
++
++ partition@c0000 {
++ label = "Bootloader";
++ reg = <0xc0000 0x0080000>;
++ };
++
++ partition@140000 {
++ label = "Config";
++ reg = <0x140000 0x0080000>;
++ };
++
++ partition@1c0000 {
++ label = "Factory";
++ reg = <0x1c0000 0x0100000>;
++ };
++
++ partition@200000 {
++ label = "firmware";
++ reg = <0x2c0000 0x2000000>;
++ };
++
++ partition@2200000 {
++ label = "User_data";
++ reg = <0x22c0000 0x4000000>;
++ };
++ };
++ };
++};
++
+ &spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spic0_pins>;
diff --git a/target/linux/mediatek/patches-5.10/140-dts-fix-wmac-support-for-mt7622-rfb1.patch b/target/linux/mediatek/patches-5.10/140-dts-fix-wmac-support-for-mt7622-rfb1.patch
new file mode 100644
index 0000000000..d6d471520f
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/140-dts-fix-wmac-support-for-mt7622-rfb1.patch
@@ -0,0 +1,18 @@
+--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+@@ -567,7 +567,7 @@
+ reg = <0x140000 0x0080000>;
+ };
+
+- partition@1c0000 {
++ factory: partition@1c0000 {
+ label = "Factory";
+ reg = <0x1c0000 0x0100000>;
+ };
+@@ -626,5 +626,6 @@
+ };
+
+ &wmac {
++ mediatek,mtd-eeprom = <&factory 0x0000>;
+ status = "okay";
+ };
diff --git a/target/linux/mediatek/patches-5.10/150-dts-mt7623-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-5.10/150-dts-mt7623-eip97-inside-secure-support.patch
new file mode 100644
index 0000000000..38947a3a94
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/150-dts-mt7623-eip97-inside-secure-support.patch
@@ -0,0 +1,23 @@
+--- a/arch/arm/boot/dts/mt7623.dtsi
++++ b/arch/arm/boot/dts/mt7623.dtsi
+@@ -949,17 +949,14 @@
+ };
+
+ crypto: crypto@1b240000 {
+- compatible = "mediatek,eip97-crypto";
++ compatible = "inside-secure,safexcel-eip97";
+ reg = <0 0x1b240000 0 0x20000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 83 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 84 IRQ_TYPE_LEVEL_LOW>,
+- <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>,
+- <GIC_SPI 97 IRQ_TYPE_LEVEL_LOW>;
++ <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
++ interrupt-names = "ring0", "ring1", "ring2", "ring3";
+ clocks = <&ethsys CLK_ETHSYS_CRYPTO>;
+- clock-names = "cryp";
+- power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>;
+- status = "disabled";
+ };
+
+ bdpsys: syscon@1c000000 {
diff --git a/target/linux/mediatek/patches-5.10/200-phy-phy-mtk-tphy-Add-hifsys-support.patch b/target/linux/mediatek/patches-5.10/200-phy-phy-mtk-tphy-Add-hifsys-support.patch
new file mode 100644
index 0000000000..bd24ddc0c0
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/200-phy-phy-mtk-tphy-Add-hifsys-support.patch
@@ -0,0 +1,66 @@
+From 28f9a5e2a3f5441ab5594669ed82da11e32277a9 Mon Sep 17 00:00:00 2001
+From: Kristian Evensen <kristian.evensen@gmail.com>
+Date: Mon, 30 Apr 2018 14:38:01 +0200
+Subject: [PATCH] phy: phy-mtk-tphy: Add hifsys-support
+
+---
+ drivers/phy/mediatek/phy-mtk-tphy.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/drivers/phy/mediatek/phy-mtk-tphy.c
++++ b/drivers/phy/mediatek/phy-mtk-tphy.c
+@@ -15,6 +15,8 @@
+ #include <linux/of_device.h>
+ #include <linux/phy/phy.h>
+ #include <linux/platform_device.h>
++#include <linux/mfd/syscon.h>
++#include <linux/regmap.h>
+
+ /* version V1 sub-banks offset base address */
+ /* banks shared by multiple phys */
+@@ -267,6 +269,9 @@
+ #define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0)
+ #define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x))
+
++#define HIF_SYSCFG1 0x14
++#define HIF_SYSCFG1_PHY2_MASK (0x3 << 20)
++
+ enum mtk_phy_version {
+ MTK_PHY_V1 = 1,
+ MTK_PHY_V2,
+@@ -315,6 +320,7 @@ struct mtk_tphy {
+ void __iomem *sif_base; /* only shared sif */
+ const struct mtk_phy_pdata *pdata;
+ struct mtk_phy_instance **phys;
++ struct regmap *hif;
+ int nphys;
+ int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */
+ int src_coef; /* coefficient for slew rate calibrate */
+@@ -634,6 +640,10 @@ static void pcie_phy_instance_init(struc
+ if (tphy->pdata->version != MTK_PHY_V1)
+ return;
+
++ if (tphy->hif)
++ regmap_update_bits(tphy->hif, HIF_SYSCFG1,
++ HIF_SYSCFG1_PHY2_MASK, 0);
++
+ tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG0);
+ tmp &= ~(P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H);
+ tmp |= P3A_RG_XTAL_EXT_PE1H_VAL(0x2) | P3A_RG_XTAL_EXT_PE2H_VAL(0x2);
+@@ -1134,6 +1144,16 @@ static int mtk_tphy_probe(struct platfor
+ &tphy->src_ref_clk);
+ device_property_read_u32(dev, "mediatek,src-coef", &tphy->src_coef);
+
++ if (of_find_property(np, "mediatek,phy-switch", NULL)) {
++ tphy->hif = syscon_regmap_lookup_by_phandle(np,
++ "mediatek,phy-switch");
++ if (IS_ERR(tphy->hif)) {
++ dev_err(&pdev->dev,
++ "missing \"mediatek,phy-switch\" phandle\n");
++ return PTR_ERR(tphy->hif);
++ }
++ }
++
+ port = 0;
+ for_each_child_of_node(np, child_np) {
+ struct mtk_phy_instance *instance;
diff --git a/target/linux/mediatek/patches-5.10/300-mtd-mtk-ecc-move-mtk-ecc-header-file-to-include-mtd.patch b/target/linux/mediatek/patches-5.10/300-mtd-mtk-ecc-move-mtk-ecc-header-file-to-include-mtd.patch
new file mode 100644
index 0000000000..d9ab339fa8
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/300-mtd-mtk-ecc-move-mtk-ecc-header-file-to-include-mtd.patch
@@ -0,0 +1,139 @@
+From a2479dc254ebe31c84fbcfda73f35e2321576494 Mon Sep 17 00:00:00 2001
+From: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+Date: Tue, 19 Mar 2019 13:57:38 +0800
+Subject: [PATCH 1/6] mtd: mtk ecc: move mtk ecc header file to include/mtd
+
+Change-Id: I8dc1d30e21b40d68ef5efd9587012f82970156a5
+Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+---
+ drivers/mtd/nand/raw/mtk_ecc.c | 3 +--
+ drivers/mtd/nand/raw/mtk_nand.c | 2 +-
+ {drivers/mtd/nand/raw => include/linux/mtd}/mtk_ecc.h | 0
+ 3 files changed, 2 insertions(+), 3 deletions(-)
+ rename {drivers/mtd/nand/raw => include/linux/mtd}/mtk_ecc.h (100%)
+
+--- a/drivers/mtd/nand/raw/mtk_ecc.c
++++ b/drivers/mtd/nand/raw/mtk_ecc.c
+@@ -15,8 +15,7 @@
+ #include <linux/of.h>
+ #include <linux/of_platform.h>
+ #include <linux/mutex.h>
+-
+-#include "mtk_ecc.h"
++#include <linux/mtd/mtk_ecc.h>
+
+ #define ECC_IDLE_MASK BIT(0)
+ #define ECC_IRQ_EN BIT(0)
+--- a/drivers/mtd/nand/raw/mtk_nand.c
++++ b/drivers/mtd/nand/raw/mtk_nand.c
+@@ -17,7 +17,7 @@
+ #include <linux/iopoll.h>
+ #include <linux/of.h>
+ #include <linux/of_device.h>
+-#include "mtk_ecc.h"
++#include <linux/mtd/mtk_ecc.h>
+
+ /* NAND controller register definition */
+ #define NFI_CNFG (0x00)
+--- /dev/null
++++ b/include/linux/mtd/mtk_ecc.h
+@@ -0,0 +1,49 @@
++/*
++ * MTK SDG1 ECC controller
++ *
++ * Copyright (c) 2016 Mediatek
++ * Authors: Xiaolei Li <xiaolei.li@mediatek.com>
++ * Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ */
++
++#ifndef __DRIVERS_MTD_NAND_MTK_ECC_H__
++#define __DRIVERS_MTD_NAND_MTK_ECC_H__
++
++#include <linux/types.h>
++
++enum mtk_ecc_mode {ECC_DMA_MODE = 0, ECC_NFI_MODE = 1};
++enum mtk_ecc_operation {ECC_ENCODE, ECC_DECODE};
++
++struct device_node;
++struct mtk_ecc;
++
++struct mtk_ecc_stats {
++ u32 corrected;
++ u32 bitflips;
++ u32 failed;
++};
++
++struct mtk_ecc_config {
++ enum mtk_ecc_operation op;
++ enum mtk_ecc_mode mode;
++ dma_addr_t addr;
++ u32 strength;
++ u32 sectors;
++ u32 len;
++};
++
++int mtk_ecc_encode(struct mtk_ecc *, struct mtk_ecc_config *, u8 *, u32);
++void mtk_ecc_get_stats(struct mtk_ecc *, struct mtk_ecc_stats *, int);
++int mtk_ecc_wait_done(struct mtk_ecc *, enum mtk_ecc_operation);
++int mtk_ecc_enable(struct mtk_ecc *, struct mtk_ecc_config *);
++void mtk_ecc_disable(struct mtk_ecc *);
++void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p);
++unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc);
++
++struct mtk_ecc *of_mtk_ecc_get(struct device_node *);
++void mtk_ecc_release(struct mtk_ecc *);
++
++#endif
+--- a/drivers/mtd/nand/raw/mtk_ecc.h
++++ /dev/null
+@@ -1,47 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+-/*
+- * MTK SDG1 ECC controller
+- *
+- * Copyright (c) 2016 Mediatek
+- * Authors: Xiaolei Li <xiaolei.li@mediatek.com>
+- * Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
+- */
+-
+-#ifndef __DRIVERS_MTD_NAND_MTK_ECC_H__
+-#define __DRIVERS_MTD_NAND_MTK_ECC_H__
+-
+-#include <linux/types.h>
+-
+-enum mtk_ecc_mode {ECC_DMA_MODE = 0, ECC_NFI_MODE = 1};
+-enum mtk_ecc_operation {ECC_ENCODE, ECC_DECODE};
+-
+-struct device_node;
+-struct mtk_ecc;
+-
+-struct mtk_ecc_stats {
+- u32 corrected;
+- u32 bitflips;
+- u32 failed;
+-};
+-
+-struct mtk_ecc_config {
+- enum mtk_ecc_operation op;
+- enum mtk_ecc_mode mode;
+- dma_addr_t addr;
+- u32 strength;
+- u32 sectors;
+- u32 len;
+-};
+-
+-int mtk_ecc_encode(struct mtk_ecc *, struct mtk_ecc_config *, u8 *, u32);
+-void mtk_ecc_get_stats(struct mtk_ecc *, struct mtk_ecc_stats *, int);
+-int mtk_ecc_wait_done(struct mtk_ecc *, enum mtk_ecc_operation);
+-int mtk_ecc_enable(struct mtk_ecc *, struct mtk_ecc_config *);
+-void mtk_ecc_disable(struct mtk_ecc *);
+-void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p);
+-unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc);
+-
+-struct mtk_ecc *of_mtk_ecc_get(struct device_node *);
+-void mtk_ecc_release(struct mtk_ecc *);
+-
+-#endif
diff --git a/target/linux/mediatek/patches-5.10/310-mtd-spinand-disable-on-die-ECC.patch b/target/linux/mediatek/patches-5.10/310-mtd-spinand-disable-on-die-ECC.patch
new file mode 100644
index 0000000000..e608113865
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/310-mtd-spinand-disable-on-die-ECC.patch
@@ -0,0 +1,31 @@
+From b341f120cfc9ca1dfd48364b7f36ac2c1fbdea43 Mon Sep 17 00:00:00 2001
+From: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+Date: Wed, 3 Apr 2019 16:30:01 +0800
+Subject: [PATCH 3/6] mtd: spinand: disable on-die ECC
+
+Change-Id: I9745adaed5295202fabbe8ab8947885c57a5b847
+Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+---
+ drivers/mtd/nand/spi/core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/mtd/nand/spi/core.c
++++ b/drivers/mtd/nand/spi/core.c
+@@ -493,7 +493,7 @@ static int spinand_mtd_read(struct mtd_i
+ int ret = 0;
+
+ if (ops->mode != MTD_OPS_RAW && spinand->eccinfo.ooblayout)
+- enable_ecc = true;
++ enable_ecc = false;
+
+ mutex_lock(&spinand->lock);
+
+@@ -541,7 +541,7 @@ static int spinand_mtd_write(struct mtd_
+ int ret = 0;
+
+ if (ops->mode != MTD_OPS_RAW && mtd->ooblayout)
+- enable_ecc = true;
++ enable_ecc = false;
+
+ mutex_lock(&spinand->lock);
+
diff --git a/target/linux/mediatek/patches-5.10/320-spi-spi-mem-MediaTek-Add-SPI-NAND-Flash-interface-dr.patch b/target/linux/mediatek/patches-5.10/320-spi-spi-mem-MediaTek-Add-SPI-NAND-Flash-interface-dr.patch
new file mode 100644
index 0000000000..53e2aed51e
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/320-spi-spi-mem-MediaTek-Add-SPI-NAND-Flash-interface-dr.patch
@@ -0,0 +1,1246 @@
+From 1ecb38eabd90efe93957d0a822a167560c39308a Mon Sep 17 00:00:00 2001
+From: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+Date: Wed, 20 Mar 2019 16:19:51 +0800
+Subject: [PATCH 6/6] spi: spi-mem: MediaTek: Add SPI NAND Flash interface
+ driver for MediaTek MT7622
+
+Change-Id: I3e78406bb9b46b0049d3988a5c71c7069e4f809c
+Signed-off-by: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
+---
+ drivers/spi/Kconfig | 9 +
+ drivers/spi/Makefile | 1 +
+ drivers/spi/spi-mtk-snfi.c | 1183 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 1193 insertions(+)
+ create mode 100644 drivers/spi/spi-mtk-snfi.c
+
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -67,6 +67,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mp
+ obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
+ obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
+ obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o
++obj-$(CONFIG_SPI_MTK_SNFI) += spi-mtk-snfi.o
+ obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o
+ obj-$(CONFIG_SPI_MTK_NOR) += spi-mtk-nor.o
+ obj-$(CONFIG_SPI_MXIC) += spi-mxic.o
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -495,6 +495,15 @@ config SPI_MT65XX
+ say Y or M here.If you are not sure, say N.
+ SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs.
+
++config SPI_MTK_SNFI
++ tristate "MediaTek SPI NAND interface"
++ select MTD_SPI_NAND
++ help
++ This selects the SPI NAND FLASH interface(SNFI),
++ which could be found on MediaTek Soc.
++ Say Y or M here.If you are not sure, say N.
++ Note Parallel Nand and SPI NAND is alternative on MediaTek SoCs.
++
+ config SPI_MT7621
+ tristate "MediaTek MT7621 SPI Controller"
+ depends on RALINK || COMPILE_TEST
+--- /dev/null
++++ b/drivers/spi/spi-mtk-snfi.c
+@@ -0,0 +1,1200 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Driver for MediaTek SPI Nand interface
++ *
++ * Copyright (C) 2018 MediaTek Inc.
++ * Authors: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
++ *
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/interrupt.h>
++#include <linux/iopoll.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/mtk_ecc.h>
++#include <linux/mtd/spinand.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/spi-mem.h>
++
++/* NAND controller register definition */
++/* NFI control */
++#define NFI_CNFG 0x00
++#define CNFG_DMA BIT(0)
++#define CNFG_READ_EN BIT(1)
++#define CNFG_DMA_BURST_EN BIT(2)
++#define CNFG_BYTE_RW BIT(6)
++#define CNFG_HW_ECC_EN BIT(8)
++#define CNFG_AUTO_FMT_EN BIT(9)
++#define CNFG_OP_PROGRAM (3UL << 12)
++#define CNFG_OP_CUST (6UL << 12)
++#define NFI_PAGEFMT 0x04
++#define PAGEFMT_512 0
++#define PAGEFMT_2K 1
++#define PAGEFMT_4K 2
++#define PAGEFMT_FDM_SHIFT 8
++#define PAGEFMT_FDM_ECC_SHIFT 12
++#define NFI_CON 0x08
++#define CON_FIFO_FLUSH BIT(0)
++#define CON_NFI_RST BIT(1)
++#define CON_BRD BIT(8)
++#define CON_BWR BIT(9)
++#define CON_SEC_SHIFT 12
++#define NFI_INTR_EN 0x10
++#define INTR_AHB_DONE_EN BIT(6)
++#define NFI_INTR_STA 0x14
++#define NFI_CMD 0x20
++#define NFI_STA 0x60
++#define STA_EMP_PAGE BIT(12)
++#define NAND_FSM_MASK (0x1f << 24)
++#define NFI_FSM_MASK (0xf << 16)
++#define NFI_ADDRCNTR 0x70
++#define CNTR_MASK GENMASK(16, 12)
++#define ADDRCNTR_SEC_SHIFT 12
++#define ADDRCNTR_SEC(val) \
++ (((val) & CNTR_MASK) >> ADDRCNTR_SEC_SHIFT)
++#define NFI_STRADDR 0x80
++#define NFI_BYTELEN 0x84
++#define NFI_CSEL 0x90
++#define NFI_FDML(x) (0xa0 + (x) * sizeof(u32) * 2)
++#define NFI_FDMM(x) (0xa4 + (x) * sizeof(u32) * 2)
++#define NFI_MASTER_STA 0x224
++#define MASTER_STA_MASK 0x0fff
++/* NFI_SPI control */
++#define SNFI_MAC_OUTL 0x504
++#define SNFI_MAC_INL 0x508
++#define SNFI_RD_CTL2 0x510
++#define RD_CMD_MASK 0x00ff
++#define RD_DUMMY_SHIFT 8
++#define SNFI_RD_CTL3 0x514
++#define RD_ADDR_MASK 0xffff
++#define SNFI_MISC_CTL 0x538
++#define RD_MODE_X2 BIT(16)
++#define RD_MODE_X4 (2UL << 16)
++#define RD_QDUAL_IO (4UL << 16)
++#define RD_MODE_MASK (7UL << 16)
++#define RD_CUSTOM_EN BIT(6)
++#define WR_CUSTOM_EN BIT(7)
++#define WR_X4_EN BIT(20)
++#define SW_RST BIT(28)
++#define SNFI_MISC_CTL2 0x53c
++#define WR_LEN_SHIFT 16
++#define SNFI_PG_CTL1 0x524
++#define WR_LOAD_CMD_SHIFT 8
++#define SNFI_PG_CTL2 0x528
++#define WR_LOAD_ADDR_MASK 0xffff
++#define SNFI_MAC_CTL 0x500
++#define MAC_WIP BIT(0)
++#define MAC_WIP_READY BIT(1)
++#define MAC_TRIG BIT(2)
++#define MAC_EN BIT(3)
++#define MAC_SIO_SEL BIT(4)
++#define SNFI_STA_CTL1 0x550
++#define SPI_STATE_IDLE 0xf
++#define SNFI_CNFG 0x55c
++#define SNFI_MODE_EN BIT(0)
++#define SNFI_GPRAM_DATA 0x800
++#define SNFI_GPRAM_MAX_LEN 16
++
++/* Dummy command trigger NFI to spi mode */
++#define NAND_CMD_DUMMYREAD 0x00
++#define NAND_CMD_DUMMYPROG 0x80
++
++#define MTK_TIMEOUT 500000
++#define MTK_RESET_TIMEOUT 1000000
++#define MTK_SNFC_MIN_SPARE 16
++#define KB(x) ((x) * 1024UL)
++
++/*
++ * supported spare size of each IP.
++ * order should be the same with the spare size bitfiled defination of
++ * register NFI_PAGEFMT.
++ */
++static const u8 spare_size_mt7622[] = {
++ 16, 26, 27, 28
++};
++
++struct mtk_snfi_caps {
++ const u8 *spare_size;
++ u8 num_spare_size;
++ u32 nand_sec_size;
++ u8 nand_fdm_size;
++ u8 nand_fdm_ecc_size;
++ u8 ecc_parity_bits;
++ u8 pageformat_spare_shift;
++ u8 bad_mark_swap;
++};
++
++struct mtk_snfi_bad_mark_ctl {
++ void (*bm_swap)(struct spi_mem *mem, u8 *buf, int raw);
++ u32 sec;
++ u32 pos;
++};
++
++struct mtk_snfi_nand_chip {
++ struct mtk_snfi_bad_mark_ctl bad_mark;
++ u32 spare_per_sector;
++};
++
++struct mtk_snfi_clk {
++ struct clk *nfi_clk;
++ struct clk *spi_clk;
++};
++
++struct mtk_snfi {
++ const struct mtk_snfi_caps *caps;
++ struct mtk_snfi_nand_chip snfi_nand;
++ struct mtk_snfi_clk clk;
++ struct mtk_ecc_config ecc_cfg;
++ struct mtk_ecc *ecc;
++ struct completion done;
++ struct device *dev;
++
++ void __iomem *regs;
++
++ u8 *buffer;
++};
++
++static inline u8 *oob_ptr(struct spi_mem *mem, int i)
++{
++ struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++ u8 *poi;
++
++ /* map the sector's FDM data to free oob:
++ * the beginning of the oob area stores the FDM data of bad mark
++ */
++
++ if (i < snfi_nand->bad_mark.sec)
++ poi = spinand->oobbuf + (i + 1) * snfi->caps->nand_fdm_size;
++ else if (i == snfi_nand->bad_mark.sec)
++ poi = spinand->oobbuf;
++ else
++ poi = spinand->oobbuf + i * snfi->caps->nand_fdm_size;
++
++ return poi;
++}
++
++static inline int mtk_data_len(struct spi_mem *mem)
++{
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++
++ return snfi->caps->nand_sec_size + snfi_nand->spare_per_sector;
++}
++
++static inline u8 *mtk_oob_ptr(struct spi_mem *mem,
++ const u8 *p, int i)
++{
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++
++ return (u8 *)p + i * mtk_data_len(mem) + snfi->caps->nand_sec_size;
++}
++
++static void mtk_snfi_bad_mark_swap(struct spi_mem *mem,
++ u8 *buf, int raw)
++{
++ struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++ u32 bad_pos = snfi_nand->bad_mark.pos;
++
++ if (raw)
++ bad_pos += snfi_nand->bad_mark.sec * mtk_data_len(mem);
++ else
++ bad_pos += snfi_nand->bad_mark.sec * snfi->caps->nand_sec_size;
++
++ swap(spinand->oobbuf[0], buf[bad_pos]);
++}
++
++static void mtk_snfi_set_bad_mark_ctl(struct mtk_snfi_bad_mark_ctl *bm_ctl,
++ struct spi_mem *mem)
++{
++ struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++ struct mtd_info *mtd = spinand_to_mtd(spinand);
++
++ bm_ctl->bm_swap = mtk_snfi_bad_mark_swap;
++ bm_ctl->sec = mtd->writesize / mtk_data_len(mem);
++ bm_ctl->pos = mtd->writesize % mtk_data_len(mem);
++}
++
++static void mtk_snfi_mac_enable(struct mtk_snfi *snfi)
++{
++ u32 mac;
++
++ mac = readl(snfi->regs + SNFI_MAC_CTL);
++ mac &= ~MAC_SIO_SEL;
++ mac |= MAC_EN;
++
++ writel(mac, snfi->regs + SNFI_MAC_CTL);
++}
++
++static int mtk_snfi_mac_trigger(struct mtk_snfi *snfi)
++{
++ u32 mac, reg;
++ int ret = 0;
++
++ mac = readl(snfi->regs + SNFI_MAC_CTL);
++ mac |= MAC_TRIG;
++ writel(mac, snfi->regs + SNFI_MAC_CTL);
++
++ ret = readl_poll_timeout_atomic(snfi->regs + SNFI_MAC_CTL, reg,
++ reg & MAC_WIP_READY, 10,
++ MTK_TIMEOUT);
++ if (ret < 0) {
++ dev_err(snfi->dev, "polling wip ready for read timeout\n");
++ return -EIO;
++ }
++
++ ret = readl_poll_timeout_atomic(snfi->regs + SNFI_MAC_CTL, reg,
++ !(reg & MAC_WIP), 10,
++ MTK_TIMEOUT);
++ if (ret < 0) {
++ dev_err(snfi->dev, "polling flash update timeout\n");
++ return -EIO;
++ }
++
++ return ret;
++}
++
++static void mtk_snfi_mac_leave(struct mtk_snfi *snfi)
++{
++ u32 mac;
++
++ mac = readl(snfi->regs + SNFI_MAC_CTL);
++ mac &= ~(MAC_TRIG | MAC_EN | MAC_SIO_SEL);
++ writel(mac, snfi->regs + SNFI_MAC_CTL);
++}
++
++static int mtk_snfi_mac_op(struct mtk_snfi *snfi)
++{
++ int ret = 0;
++
++ mtk_snfi_mac_enable(snfi);
++
++ ret = mtk_snfi_mac_trigger(snfi);
++ if (ret)
++ return ret;
++
++ mtk_snfi_mac_leave(snfi);
++
++ return ret;
++}
++
++static irqreturn_t mtk_snfi_irq(int irq, void *id)
++{
++ struct mtk_snfi *snfi = id;
++ u16 sta, ien;
++
++ sta = readw(snfi->regs + NFI_INTR_STA);
++ ien = readw(snfi->regs + NFI_INTR_EN);
++
++ if (!(sta & ien))
++ return IRQ_NONE;
++
++ writew(~sta & ien, snfi->regs + NFI_INTR_EN);
++ complete(&snfi->done);
++
++ return IRQ_HANDLED;
++}
++
++static int mtk_snfi_enable_clk(struct device *dev, struct mtk_snfi_clk *clk)
++{
++ int ret;
++
++ ret = clk_prepare_enable(clk->nfi_clk);
++ if (ret) {
++ dev_err(dev, "failed to enable nfi clk\n");
++ return ret;
++ }
++
++ ret = clk_prepare_enable(clk->spi_clk);
++ if (ret) {
++ dev_err(dev, "failed to enable spi clk\n");
++ clk_disable_unprepare(clk->nfi_clk);
++ return ret;
++ }
++
++ return 0;
++}
++
++static void mtk_snfi_disable_clk(struct mtk_snfi_clk *clk)
++{
++ clk_disable_unprepare(clk->nfi_clk);
++ clk_disable_unprepare(clk->spi_clk);
++}
++
++static int mtk_snfi_reset(struct mtk_snfi *snfi)
++{
++ u32 val;
++ int ret;
++
++ /* SW reset controller */
++ val = readl(snfi->regs + SNFI_MISC_CTL) | SW_RST;
++ writel(val, snfi->regs + SNFI_MISC_CTL);
++
++ ret = readw_poll_timeout(snfi->regs + SNFI_STA_CTL1, val,
++ !(val & SPI_STATE_IDLE), 50,
++ MTK_RESET_TIMEOUT);
++ if (ret) {
++ dev_warn(snfi->dev, "spi state active in reset [0x%x] = 0x%x\n",
++ SNFI_STA_CTL1, val);
++ return ret;
++ }
++
++ val = readl(snfi->regs + SNFI_MISC_CTL);
++ val &= ~SW_RST;
++ writel(val, snfi->regs + SNFI_MISC_CTL);
++
++ /* reset all registers and force the NFI master to terminate */
++ writew(CON_FIFO_FLUSH | CON_NFI_RST, snfi->regs + NFI_CON);
++ ret = readw_poll_timeout(snfi->regs + NFI_STA, val,
++ !(val & (NFI_FSM_MASK | NAND_FSM_MASK)), 50,
++ MTK_RESET_TIMEOUT);
++ if (ret) {
++ dev_warn(snfi->dev, "nfi active in reset [0x%x] = 0x%x\n",
++ NFI_STA, val);
++ return ret;
++ }
++
++ return 0;
++}
++
++static int mtk_snfi_set_spare_per_sector(struct spinand_device *spinand,
++ const struct mtk_snfi_caps *caps,
++ u32 *sps)
++{
++ struct mtd_info *mtd = spinand_to_mtd(spinand);
++ const u8 *spare = caps->spare_size;
++ u32 sectors, i, closest_spare = 0;
++
++ sectors = mtd->writesize / caps->nand_sec_size;
++ *sps = mtd->oobsize / sectors;
++
++ if (*sps < MTK_SNFC_MIN_SPARE)
++ return -EINVAL;
++
++ for (i = 0; i < caps->num_spare_size; i++) {
++ if (*sps >= spare[i] && spare[i] >= spare[closest_spare]) {
++ closest_spare = i;
++ if (*sps == spare[i])
++ break;
++ }
++ }
++
++ *sps = spare[closest_spare];
++
++ return 0;
++}
++
++static void mtk_snfi_read_fdm_data(struct spi_mem *mem,
++ u32 sectors)
++{
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++ const struct mtk_snfi_caps *caps = snfi->caps;
++ u32 vall, valm;
++ int i, j;
++ u8 *oobptr;
++
++ for (i = 0; i < sectors; i++) {
++ oobptr = oob_ptr(mem, i);
++ vall = readl(snfi->regs + NFI_FDML(i));
++ valm = readl(snfi->regs + NFI_FDMM(i));
++
++ for (j = 0; j < caps->nand_fdm_size; j++)
++ oobptr[j] = (j >= 4 ? valm : vall) >> ((j % 4) * 8);
++ }
++}
++
++static void mtk_snfi_write_fdm_data(struct spi_mem *mem,
++ u32 sectors)
++{
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++ const struct mtk_snfi_caps *caps = snfi->caps;
++ u32 vall, valm;
++ int i, j;
++ u8 *oobptr;
++
++ for (i = 0; i < sectors; i++) {
++ oobptr = oob_ptr(mem, i);
++ vall = 0;
++ valm = 0;
++ for (j = 0; j < 8; j++) {
++ if (j < 4)
++ vall |= (j < caps->nand_fdm_size ? oobptr[j] :
++ 0xff) << (j * 8);
++ else
++ valm |= (j < caps->nand_fdm_size ? oobptr[j] :
++ 0xff) << ((j - 4) * 8);
++ }
++ writel(vall, snfi->regs + NFI_FDML(i));
++ writel(valm, snfi->regs + NFI_FDMM(i));
++ }
++}
++
++static int mtk_snfi_update_ecc_stats(struct spi_mem *mem,
++ u8 *buf, u32 sectors)
++{
++ struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++ struct mtd_info *mtd = spinand_to_mtd(spinand);
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++ struct mtk_ecc_stats stats;
++ int rc, i;
++
++ rc = readl(snfi->regs + NFI_STA) & STA_EMP_PAGE;
++ if (rc) {
++ memset(buf, 0xff, sectors * snfi->caps->nand_sec_size);
++ for (i = 0; i < sectors; i++)
++ memset(spinand->oobbuf, 0xff,
++ snfi->caps->nand_fdm_size);
++ return 0;
++ }
++
++ mtk_ecc_get_stats(snfi->ecc, &stats, sectors);
++ mtd->ecc_stats.corrected += stats.corrected;
++ mtd->ecc_stats.failed += stats.failed;
++
++ return 0;
++}
++
++static int mtk_snfi_hw_runtime_config(struct spi_mem *mem)
++{
++ struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++ struct mtd_info *mtd = spinand_to_mtd(spinand);
++ struct nand_device *nand = mtd_to_nanddev(mtd);
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++ const struct mtk_snfi_caps *caps = snfi->caps;
++ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++ u32 fmt, spare, i = 0;
++ int ret;
++
++ ret = mtk_snfi_set_spare_per_sector(spinand, caps, &spare);
++ if (ret)
++ return ret;
++
++ /* calculate usable oob bytes for ecc parity data */
++ snfi_nand->spare_per_sector = spare;
++ spare -= caps->nand_fdm_size;
++
++ nand->memorg.oobsize = snfi_nand->spare_per_sector
++ * (mtd->writesize / caps->nand_sec_size);
++ mtd->oobsize = nanddev_per_page_oobsize(nand);
++
++ snfi->ecc_cfg.strength = (spare << 3) / caps->ecc_parity_bits;
++ mtk_ecc_adjust_strength(snfi->ecc, &snfi->ecc_cfg.strength);
++
++ switch (mtd->writesize) {
++ case 512:
++ fmt = PAGEFMT_512;
++ break;
++ case KB(2):
++ fmt = PAGEFMT_2K;
++ break;
++ case KB(4):
++ fmt = PAGEFMT_4K;
++ break;
++ default:
++ dev_err(snfi->dev, "invalid page len: %d\n", mtd->writesize);
++ return -EINVAL;
++ }
++
++ /* Setup PageFormat */
++ while (caps->spare_size[i] != snfi_nand->spare_per_sector) {
++ i++;
++ if (i == (caps->num_spare_size - 1)) {
++ dev_err(snfi->dev, "invalid spare size %d\n",
++ snfi_nand->spare_per_sector);
++ return -EINVAL;
++ }
++ }
++
++ fmt |= i << caps->pageformat_spare_shift;
++ fmt |= caps->nand_fdm_size << PAGEFMT_FDM_SHIFT;
++ fmt |= caps->nand_fdm_ecc_size << PAGEFMT_FDM_ECC_SHIFT;
++ writel(fmt, snfi->regs + NFI_PAGEFMT);
++
++ snfi->ecc_cfg.len = caps->nand_sec_size + caps->nand_fdm_ecc_size;
++
++ mtk_snfi_set_bad_mark_ctl(&snfi_nand->bad_mark, mem);
++
++ return 0;
++}
++
++static int mtk_snfi_read_from_cache(struct spi_mem *mem,
++ const struct spi_mem_op *op, int oob_on)
++{
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++ struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++ struct mtd_info *mtd = spinand_to_mtd(spinand);
++ u32 sectors = mtd->writesize / snfi->caps->nand_sec_size;
++ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++ u32 reg, len, col_addr = 0;
++ int dummy_cycle, ret;
++ dma_addr_t dma_addr;
++
++ len = sectors * (snfi->caps->nand_sec_size
++ + snfi_nand->spare_per_sector);
++
++ dma_addr = dma_map_single(snfi->dev, snfi->buffer,
++ len, DMA_FROM_DEVICE);
++ ret = dma_mapping_error(snfi->dev, dma_addr);
++ if (ret) {
++ dev_err(snfi->dev, "dma mapping error\n");
++ return -EINVAL;
++ }
++
++ /* set Read cache command and dummy cycle */
++ dummy_cycle = (op->dummy.nbytes << 3) >> (ffs(op->dummy.buswidth) - 1);
++ reg = ((op->cmd.opcode & RD_CMD_MASK) |
++ (dummy_cycle << RD_DUMMY_SHIFT));
++ writel(reg, snfi->regs + SNFI_RD_CTL2);
++
++ writel((col_addr & RD_ADDR_MASK), snfi->regs + SNFI_RD_CTL3);
++
++ reg = readl(snfi->regs + SNFI_MISC_CTL);
++ reg |= RD_CUSTOM_EN;
++ reg &= ~(RD_MODE_MASK | WR_X4_EN);
++
++ /* set data and addr buswidth */
++ if (op->data.buswidth == 4)
++ reg |= RD_MODE_X4;
++ else if (op->data.buswidth == 2)
++ reg |= RD_MODE_X2;
++
++ if (op->addr.buswidth == 4 || op->addr.buswidth == 2)
++ reg |= RD_QDUAL_IO;
++ writel(reg, snfi->regs + SNFI_MISC_CTL);
++
++ writel(len, snfi->regs + SNFI_MISC_CTL2);
++ writew(sectors << CON_SEC_SHIFT, snfi->regs + NFI_CON);
++ reg = readw(snfi->regs + NFI_CNFG);
++ reg |= CNFG_READ_EN | CNFG_DMA_BURST_EN | CNFG_DMA | CNFG_OP_CUST;
++
++ if (!oob_on) {
++ reg |= CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN;
++ writew(reg, snfi->regs + NFI_CNFG);
++
++ snfi->ecc_cfg.mode = ECC_NFI_MODE;
++ snfi->ecc_cfg.sectors = sectors;
++ snfi->ecc_cfg.op = ECC_DECODE;
++ ret = mtk_ecc_enable(snfi->ecc, &snfi->ecc_cfg);
++ if (ret) {
++ dev_err(snfi->dev, "ecc enable failed\n");
++ /* clear NFI_CNFG */
++ reg &= ~(CNFG_READ_EN | CNFG_DMA_BURST_EN | CNFG_DMA |
++ CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN);
++ writew(reg, snfi->regs + NFI_CNFG);
++ goto out;
++ }
++ } else {
++ writew(reg, snfi->regs + NFI_CNFG);
++ }
++
++ writel(lower_32_bits(dma_addr), snfi->regs + NFI_STRADDR);
++ readw(snfi->regs + NFI_INTR_STA);
++ writew(INTR_AHB_DONE_EN, snfi->regs + NFI_INTR_EN);
++
++ init_completion(&snfi->done);
++
++ /* set dummy command to trigger NFI enter SPI mode */
++ writew(NAND_CMD_DUMMYREAD, snfi->regs + NFI_CMD);
++ reg = readl(snfi->regs + NFI_CON) | CON_BRD;
++ writew(reg, snfi->regs + NFI_CON);
++
++ ret = wait_for_completion_timeout(&snfi->done, msecs_to_jiffies(500));
++ if (!ret) {
++ dev_err(snfi->dev, "read ahb done timeout\n");
++ writew(0, snfi->regs + NFI_INTR_EN);
++ ret = -ETIMEDOUT;
++ goto out;
++ }
++
++ ret = readl_poll_timeout_atomic(snfi->regs + NFI_BYTELEN, reg,
++ ADDRCNTR_SEC(reg) >= sectors, 10,
++ MTK_TIMEOUT);
++ if (ret < 0) {
++ dev_err(snfi->dev, "polling read byte len timeout\n");
++ ret = -EIO;
++ } else {
++ if (!oob_on) {
++ ret = mtk_ecc_wait_done(snfi->ecc, ECC_DECODE);
++ if (ret) {
++ dev_warn(snfi->dev, "wait ecc done timeout\n");
++ } else {
++ mtk_snfi_update_ecc_stats(mem, snfi->buffer,
++ sectors);
++ mtk_snfi_read_fdm_data(mem, sectors);
++ }
++ }
++ }
++
++ if (oob_on)
++ goto out;
++
++ mtk_ecc_disable(snfi->ecc);
++out:
++ dma_unmap_single(snfi->dev, dma_addr, len, DMA_FROM_DEVICE);
++ writel(0, snfi->regs + NFI_CON);
++ writel(0, snfi->regs + NFI_CNFG);
++ reg = readl(snfi->regs + SNFI_MISC_CTL);
++ reg &= ~RD_CUSTOM_EN;
++ writel(reg, snfi->regs + SNFI_MISC_CTL);
++
++ return ret;
++}
++
++static int mtk_snfi_write_to_cache(struct spi_mem *mem,
++ const struct spi_mem_op *op,
++ int oob_on)
++{
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++ struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++ struct mtd_info *mtd = spinand_to_mtd(spinand);
++ u32 sectors = mtd->writesize / snfi->caps->nand_sec_size;
++ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++ u32 reg, len, col_addr = 0;
++ dma_addr_t dma_addr;
++ int ret;
++
++ len = sectors * (snfi->caps->nand_sec_size
++ + snfi_nand->spare_per_sector);
++
++ dma_addr = dma_map_single(snfi->dev, snfi->buffer, len,
++ DMA_TO_DEVICE);
++ ret = dma_mapping_error(snfi->dev, dma_addr);
++ if (ret) {
++ dev_err(snfi->dev, "dma mapping error\n");
++ return -EINVAL;
++ }
++
++ /* set program load cmd and address */
++ reg = (op->cmd.opcode << WR_LOAD_CMD_SHIFT);
++ writel(reg, snfi->regs + SNFI_PG_CTL1);
++ writel(col_addr & WR_LOAD_ADDR_MASK, snfi->regs + SNFI_PG_CTL2);
++
++ reg = readl(snfi->regs + SNFI_MISC_CTL);
++ reg |= WR_CUSTOM_EN;
++ reg &= ~(RD_MODE_MASK | WR_X4_EN);
++
++ if (op->data.buswidth == 4)
++ reg |= WR_X4_EN;
++ writel(reg, snfi->regs + SNFI_MISC_CTL);
++
++ writel(len << WR_LEN_SHIFT, snfi->regs + SNFI_MISC_CTL2);
++ writew(sectors << CON_SEC_SHIFT, snfi->regs + NFI_CON);
++
++ reg = readw(snfi->regs + NFI_CNFG);
++ reg &= ~(CNFG_READ_EN | CNFG_BYTE_RW);
++ reg |= CNFG_DMA | CNFG_DMA_BURST_EN | CNFG_OP_PROGRAM;
++
++ if (!oob_on) {
++ reg |= CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN;
++ writew(reg, snfi->regs + NFI_CNFG);
++
++ snfi->ecc_cfg.mode = ECC_NFI_MODE;
++ snfi->ecc_cfg.op = ECC_ENCODE;
++ ret = mtk_ecc_enable(snfi->ecc, &snfi->ecc_cfg);
++ if (ret) {
++ dev_err(snfi->dev, "ecc enable failed\n");
++ /* clear NFI_CNFG */
++ reg &= ~(CNFG_DMA_BURST_EN | CNFG_DMA |
++ CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN);
++ writew(reg, snfi->regs + NFI_CNFG);
++ dma_unmap_single(snfi->dev, dma_addr, len,
++ DMA_FROM_DEVICE);
++ goto out;
++ }
++ /* write OOB into the FDM registers (OOB area in MTK NAND) */
++ mtk_snfi_write_fdm_data(mem, sectors);
++ } else {
++ writew(reg, snfi->regs + NFI_CNFG);
++ }
++ writel(lower_32_bits(dma_addr), snfi->regs + NFI_STRADDR);
++ readw(snfi->regs + NFI_INTR_STA);
++ writew(INTR_AHB_DONE_EN, snfi->regs + NFI_INTR_EN);
++
++ init_completion(&snfi->done);
++
++ /* set dummy command to trigger NFI enter SPI mode */
++ writew(NAND_CMD_DUMMYPROG, snfi->regs + NFI_CMD);
++ reg = readl(snfi->regs + NFI_CON) | CON_BWR;
++ writew(reg, snfi->regs + NFI_CON);
++
++ ret = wait_for_completion_timeout(&snfi->done, msecs_to_jiffies(500));
++ if (!ret) {
++ dev_err(snfi->dev, "custom program done timeout\n");
++ writew(0, snfi->regs + NFI_INTR_EN);
++ ret = -ETIMEDOUT;
++ goto ecc_disable;
++ }
++
++ ret = readl_poll_timeout_atomic(snfi->regs + NFI_ADDRCNTR, reg,
++ ADDRCNTR_SEC(reg) >= sectors,
++ 10, MTK_TIMEOUT);
++ if (ret)
++ dev_err(snfi->dev, "hwecc write timeout\n");
++
++ecc_disable:
++ mtk_ecc_disable(snfi->ecc);
++
++out:
++ dma_unmap_single(snfi->dev, dma_addr, len, DMA_TO_DEVICE);
++ writel(0, snfi->regs + NFI_CON);
++ writel(0, snfi->regs + NFI_CNFG);
++ reg = readl(snfi->regs + SNFI_MISC_CTL);
++ reg &= ~WR_CUSTOM_EN;
++ writel(reg, snfi->regs + SNFI_MISC_CTL);
++
++ return ret;
++}
++
++static int mtk_snfi_read(struct spi_mem *mem,
++ const struct spi_mem_op *op)
++{
++ struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++ struct mtd_info *mtd = spinand_to_mtd(spinand);
++ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++ u32 col_addr = op->addr.val;
++ int i, ret, sectors, oob_on = false;
++
++ if (col_addr == mtd->writesize)
++ oob_on = true;
++
++ ret = mtk_snfi_read_from_cache(mem, op, oob_on);
++ if (ret) {
++ dev_warn(snfi->dev, "read from cache fail\n");
++ return ret;
++ }
++
++ sectors = mtd->writesize / snfi->caps->nand_sec_size;
++ for (i = 0; i < sectors; i++) {
++ if (oob_on)
++ memcpy(oob_ptr(mem, i),
++ mtk_oob_ptr(mem, snfi->buffer, i),
++ snfi->caps->nand_fdm_size);
++
++ if (i == snfi_nand->bad_mark.sec && snfi->caps->bad_mark_swap)
++ snfi_nand->bad_mark.bm_swap(mem, snfi->buffer,
++ oob_on);
++ }
++
++ if (!oob_on)
++ memcpy(spinand->databuf, snfi->buffer, mtd->writesize);
++
++ return ret;
++}
++
++static int mtk_snfi_write(struct spi_mem *mem,
++ const struct spi_mem_op *op)
++{
++ struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++ struct mtd_info *mtd = spinand_to_mtd(spinand);
++ struct mtk_snfi_nand_chip *snfi_nand = &snfi->snfi_nand;
++ u32 ret, i, sectors, col_addr = op->addr.val;
++ int oob_on = false;
++
++ if (col_addr == mtd->writesize)
++ oob_on = true;
++
++ sectors = mtd->writesize / snfi->caps->nand_sec_size;
++ memset(snfi->buffer, 0xff, mtd->writesize + mtd->oobsize);
++
++ if (!oob_on)
++ memcpy(snfi->buffer, spinand->databuf, mtd->writesize);
++
++ for (i = 0; i < sectors; i++) {
++ if (i == snfi_nand->bad_mark.sec && snfi->caps->bad_mark_swap)
++ snfi_nand->bad_mark.bm_swap(mem, snfi->buffer, oob_on);
++
++ if (oob_on)
++ memcpy(mtk_oob_ptr(mem, snfi->buffer, i),
++ oob_ptr(mem, i),
++ snfi->caps->nand_fdm_size);
++ }
++
++ ret = mtk_snfi_write_to_cache(mem, op, oob_on);
++ if (ret)
++ dev_warn(snfi->dev, "write to cache fail\n");
++
++ return ret;
++}
++
++static int mtk_snfi_command_exec(struct mtk_snfi *snfi,
++ const u8 *txbuf, u8 *rxbuf,
++ const u32 txlen, const u32 rxlen)
++{
++ u32 tmp, i, j, reg, m;
++ u8 *p_tmp = (u8 *)(&tmp);
++ int ret = 0;
++
++ /* Moving tx data to NFI_SPI GPRAM */
++ for (i = 0, m = 0; i < txlen; ) {
++ for (j = 0, tmp = 0; i < txlen && j < 4; i++, j++)
++ p_tmp[j] = txbuf[i];
++
++ writel(tmp, snfi->regs + SNFI_GPRAM_DATA + m);
++ m += 4;
++ }
++
++ writel(txlen, snfi->regs + SNFI_MAC_OUTL);
++ writel(rxlen, snfi->regs + SNFI_MAC_INL);
++ ret = mtk_snfi_mac_op(snfi);
++ if (ret)
++ return ret;
++
++ /* For NULL input data, this loop will be skipped */
++ if (rxlen)
++ for (i = 0, m = 0; i < rxlen; ) {
++ reg = readl(snfi->regs +
++ SNFI_GPRAM_DATA + m);
++ for (j = 0; i < rxlen && j < 4; i++, j++, rxbuf++) {
++ if (m == 0 && i == 0)
++ j = i + txlen;
++ *rxbuf = (reg >> (j * 8)) & 0xFF;
++ }
++ m += 4;
++ }
++
++ return ret;
++}
++
++/*
++ * mtk_snfi_exec_op - to process command/data to send to the
++ * SPI NAND by mtk controller
++ */
++static int mtk_snfi_exec_op(struct spi_mem *mem,
++ const struct spi_mem_op *op)
++
++{
++ struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
++ struct spinand_device *spinand = spi_mem_get_drvdata(mem);
++ struct mtd_info *mtd = spinand_to_mtd(spinand);
++ struct nand_device *nand = mtd_to_nanddev(mtd);
++ const struct spi_mem_op *read_cache;
++ const struct spi_mem_op *write_cache;
++ const struct spi_mem_op *update_cache;
++ u32 tmpbufsize, txlen = 0, rxlen = 0;
++ u8 *txbuf, *rxbuf = NULL, *buf;
++ int i, ret = 0;
++
++ ret = mtk_snfi_reset(snfi);
++ if (ret) {
++ dev_warn(snfi->dev, "reset spi memory controller fail\n");
++ return ret;
++ }
++
++ /*if bbt initial, framework have detect nand information */
++ if (nand->bbt.cache) {
++ read_cache = spinand->op_templates.read_cache;
++ write_cache = spinand->op_templates.write_cache;
++ update_cache = spinand->op_templates.update_cache;
++
++ ret = mtk_snfi_hw_runtime_config(mem);
++ if (ret)
++ return ret;
++
++ /* For Read/Write with cache, Erase use framework flow */
++ if (op->cmd.opcode == read_cache->cmd.opcode) {
++ ret = mtk_snfi_read(mem, op);
++ if (ret)
++ dev_warn(snfi->dev, "snfi read fail\n");
++
++ return ret;
++ } else if ((op->cmd.opcode == write_cache->cmd.opcode)
++ || (op->cmd.opcode == update_cache->cmd.opcode)) {
++ ret = mtk_snfi_write(mem, op);
++ if (ret)
++ dev_warn(snfi->dev, "snfi write fail\n");
++
++ return ret;
++ }
++ }
++
++ tmpbufsize = sizeof(op->cmd.opcode) + op->addr.nbytes +
++ op->dummy.nbytes + op->data.nbytes;
++
++ txbuf = kzalloc(tmpbufsize, GFP_KERNEL);
++ if (!txbuf)
++ return -ENOMEM;
++
++ txbuf[txlen++] = op->cmd.opcode;
++
++ if (op->addr.nbytes)
++ for (i = 0; i < op->addr.nbytes; i++)
++ txbuf[txlen++] = op->addr.val >>
++ (8 * (op->addr.nbytes - i - 1));
++
++ txlen += op->dummy.nbytes;
++
++ if (op->data.dir == SPI_MEM_DATA_OUT)
++ for (i = 0; i < op->data.nbytes; i++) {
++ buf = (u8 *)op->data.buf.out;
++ txbuf[txlen++] = buf[i];
++ }
++
++ if (op->data.dir == SPI_MEM_DATA_IN) {
++ rxbuf = (u8 *)op->data.buf.in;
++ rxlen += op->data.nbytes;
++ }
++
++ ret = mtk_snfi_command_exec(snfi, txbuf, rxbuf, txlen, rxlen);
++ kfree(txbuf);
++
++ return ret;
++}
++
++static int mtk_snfi_init(struct mtk_snfi *snfi)
++{
++ int ret;
++
++ /* Reset the state machine and data FIFO */
++ ret = mtk_snfi_reset(snfi);
++ if (ret) {
++ dev_warn(snfi->dev, "MTK reset controller fail\n");
++ return ret;
++ }
++
++ snfi->buffer = devm_kzalloc(snfi->dev, 4096 + 256, GFP_KERNEL);
++ if (!snfi->buffer)
++ return -ENOMEM;
++
++ /* Clear interrupt, read clear. */
++ readw(snfi->regs + NFI_INTR_STA);
++ writew(0, snfi->regs + NFI_INTR_EN);
++
++ writel(0, snfi->regs + NFI_CON);
++ writel(0, snfi->regs + NFI_CNFG);
++
++ /* Change to NFI_SPI mode. */
++ writel(SNFI_MODE_EN, snfi->regs + SNFI_CNFG);
++
++ return 0;
++}
++
++static int mtk_snfi_check_buswidth(u8 width)
++{
++ switch (width) {
++ case 1:
++ case 2:
++ case 4:
++ return 0;
++
++ default:
++ break;
++ }
++
++ return -ENOTSUPP;
++}
++
++static bool mtk_snfi_supports_op(struct spi_mem *mem,
++ const struct spi_mem_op *op)
++{
++ int ret = 0;
++
++ /* For MTK Spi Nand controller, cmd buswidth just support 1 bit*/
++ if (op->cmd.buswidth != 1)
++ ret = -ENOTSUPP;
++
++ if (op->addr.nbytes)
++ ret |= mtk_snfi_check_buswidth(op->addr.buswidth);
++
++ if (op->dummy.nbytes)
++ ret |= mtk_snfi_check_buswidth(op->dummy.buswidth);
++
++ if (op->data.nbytes)
++ ret |= mtk_snfi_check_buswidth(op->data.buswidth);
++
++ if (ret)
++ return false;
++
++ return true;
++}
++
++static const struct spi_controller_mem_ops mtk_snfi_ops = {
++ .supports_op = mtk_snfi_supports_op,
++ .exec_op = mtk_snfi_exec_op,
++};
++
++static const struct mtk_snfi_caps snfi_mt7622 = {
++ .spare_size = spare_size_mt7622,
++ .num_spare_size = 4,
++ .nand_sec_size = 512,
++ .nand_fdm_size = 8,
++ .nand_fdm_ecc_size = 1,
++ .ecc_parity_bits = 13,
++ .pageformat_spare_shift = 4,
++ .bad_mark_swap = 0,
++};
++
++static const struct mtk_snfi_caps snfi_mt7629 = {
++ .spare_size = spare_size_mt7622,
++ .num_spare_size = 4,
++ .nand_sec_size = 512,
++ .nand_fdm_size = 8,
++ .nand_fdm_ecc_size = 1,
++ .ecc_parity_bits = 13,
++ .pageformat_spare_shift = 4,
++ .bad_mark_swap = 1,
++};
++
++static const struct of_device_id mtk_snfi_id_table[] = {
++ { .compatible = "mediatek,mt7622-snfi", .data = &snfi_mt7622, },
++ { .compatible = "mediatek,mt7629-snfi", .data = &snfi_mt7629, },
++ { /* sentinel */ }
++};
++
++static int mtk_snfi_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *np = dev->of_node;
++ struct spi_controller *ctlr;
++ struct mtk_snfi *snfi;
++ struct resource *res;
++ int ret = 0, irq;
++
++ ctlr = spi_alloc_master(&pdev->dev, sizeof(*snfi));
++ if (!ctlr)
++ return -ENOMEM;
++
++ snfi = spi_controller_get_devdata(ctlr);
++ snfi->caps = of_device_get_match_data(dev);
++ snfi->dev = dev;
++
++ snfi->ecc = of_mtk_ecc_get(np);
++ if (IS_ERR_OR_NULL(snfi->ecc))
++ goto err_put_master;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ snfi->regs = devm_ioremap_resource(dev, res);
++ if (IS_ERR(snfi->regs)) {
++ ret = PTR_ERR(snfi->regs);
++ goto release_ecc;
++ }
++
++ /* find the clocks */
++ snfi->clk.nfi_clk = devm_clk_get(dev, "nfi_clk");
++ if (IS_ERR(snfi->clk.nfi_clk)) {
++ dev_err(dev, "no nfi clk\n");
++ ret = PTR_ERR(snfi->clk.nfi_clk);
++ goto release_ecc;
++ }
++
++ snfi->clk.spi_clk = devm_clk_get(dev, "spi_clk");
++ if (IS_ERR(snfi->clk.spi_clk)) {
++ dev_err(dev, "no spi clk\n");
++ ret = PTR_ERR(snfi->clk.spi_clk);
++ goto release_ecc;
++ }
++
++ ret = mtk_snfi_enable_clk(dev, &snfi->clk);
++ if (ret)
++ goto release_ecc;
++
++ /* find the irq */
++ irq = platform_get_irq(pdev, 0);
++ if (irq < 0) {
++ dev_err(dev, "no snfi irq resource\n");
++ ret = -EINVAL;
++ goto clk_disable;
++ }
++
++ ret = devm_request_irq(dev, irq, mtk_snfi_irq, 0, "mtk-snfi", snfi);
++ if (ret) {
++ dev_err(dev, "failed to request snfi irq\n");
++ goto clk_disable;
++ }
++
++ ret = dma_set_mask(dev, DMA_BIT_MASK(32));
++ if (ret) {
++ dev_err(dev, "failed to set dma mask\n");
++ goto clk_disable;
++ }
++
++ ctlr->dev.of_node = np;
++ ctlr->mem_ops = &mtk_snfi_ops;
++
++ platform_set_drvdata(pdev, snfi);
++ ret = mtk_snfi_init(snfi);
++ if (ret) {
++ dev_err(dev, "failed to init snfi\n");
++ goto clk_disable;
++ }
++
++ ret = devm_spi_register_master(dev, ctlr);
++ if (ret)
++ goto clk_disable;
++
++ return 0;
++
++clk_disable:
++ mtk_snfi_disable_clk(&snfi->clk);
++
++release_ecc:
++ mtk_ecc_release(snfi->ecc);
++
++err_put_master:
++ spi_master_put(ctlr);
++
++ dev_err(dev, "MediaTek SPI NAND interface probe failed %d\n", ret);
++ return ret;
++}
++
++static int mtk_snfi_remove(struct platform_device *pdev)
++{
++ struct mtk_snfi *snfi = platform_get_drvdata(pdev);
++
++ mtk_snfi_disable_clk(&snfi->clk);
++
++ return 0;
++}
++
++static int mtk_snfi_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ struct mtk_snfi *snfi = platform_get_drvdata(pdev);
++
++ mtk_snfi_disable_clk(&snfi->clk);
++
++ return 0;
++}
++
++static int mtk_snfi_resume(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct mtk_snfi *snfi = dev_get_drvdata(dev);
++ int ret;
++
++ ret = mtk_snfi_enable_clk(dev, &snfi->clk);
++ if (ret)
++ return ret;
++
++ ret = mtk_snfi_init(snfi);
++ if (ret)
++ dev_err(dev, "failed to init snfi controller\n");
++
++ return ret;
++}
++
++static struct platform_driver mtk_snfi_driver = {
++ .driver = {
++ .name = "mtk-snfi",
++ .of_match_table = mtk_snfi_id_table,
++ },
++ .probe = mtk_snfi_probe,
++ .remove = mtk_snfi_remove,
++ .suspend = mtk_snfi_suspend,
++ .resume = mtk_snfi_resume,
++};
++
++module_platform_driver(mtk_snfi_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Xiangsheng Hou <xiangsheng.hou@mediatek.com>");
++MODULE_DESCRIPTION("Mediatek SPI Memory Interface Driver");
diff --git a/target/linux/mediatek/patches-5.10/330-mtk-bmt-support.patch b/target/linux/mediatek/patches-5.10/330-mtk-bmt-support.patch
new file mode 100644
index 0000000000..5c20952611
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/330-mtk-bmt-support.patch
@@ -0,0 +1,840 @@
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -15,6 +15,10 @@ config MTD_NAND_ECC
+ bool
+ depends on MTD_NAND_CORE
+
++config MTD_NAND_MTK_BMT
++ bool "Support MediaTek NAND Bad-block Management Table"
++ default n
++
+ endmenu
+
+ endmenu
+--- a/drivers/mtd/nand/Makefile
++++ b/drivers/mtd/nand/Makefile
+@@ -2,6 +2,7 @@
+
+ nandcore-objs := core.o bbt.o
+ obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
++obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o
+
+ obj-y += onenand/
+ obj-y += raw/
+--- /dev/null
++++ b/drivers/mtd/nand/mtk_bmt.c
+@@ -0,0 +1,766 @@
++/*
++ * Copyright (c) 2017 MediaTek Inc.
++ * Author: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
++ * Copyright (c) 2020 Felix Fietkau <nbd@nbd.name>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++#include <linux/slab.h>
++#include <linux/gfp.h>
++#include <linux/kernel.h>
++#include <linux/of.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/partitions.h>
++#include <linux/mtd/mtk_bmt.h>
++#include <linux/module.h>
++#include <linux/debugfs.h>
++
++#define MAIN_SIGNATURE_OFFSET 0
++#define OOB_SIGNATURE_OFFSET 1
++#define BBPOOL_RATIO 2
++
++#define BBT_LOG(fmt, ...) pr_debug("[BBT][%s|%d] "fmt"\n", __func__, __LINE__, ##__VA_ARGS__)
++
++/* Maximum 8k blocks */
++#define BB_TABLE_MAX 0x2000U
++#define BMT_TABLE_MAX (BB_TABLE_MAX * BBPOOL_RATIO / 100)
++#define BMT_TBL_DEF_VAL 0x0
++
++/*
++ * Burner Bad Block Table
++ * --------- Only support SLC Nand Chips!!!!!!!!!!! ----------
++ */
++
++struct bbbt {
++ char signature[3];
++ /* This version is used to distinguish the legacy and new algorithm */
++#define BBMT_VERSION 2
++ unsigned char version;
++ /* Below 2 tables will be written in SLC */
++ u16 bb_tbl[BB_TABLE_MAX];
++ struct bbmt {
++ u16 block;
++#define NO_MAPPED 0
++#define NORMAL_MAPPED 1
++#define BMT_MAPPED 2
++ u16 mapped;
++ } bmt_tbl[BMT_TABLE_MAX];
++};
++
++static struct bmt_desc {
++ struct mtd_info *mtd;
++
++ int (*_read_oob) (struct mtd_info *mtd, loff_t from,
++ struct mtd_oob_ops *ops);
++ int (*_write_oob) (struct mtd_info *mtd, loff_t to,
++ struct mtd_oob_ops *ops);
++ const struct nand_ops *nand_ops;
++
++ struct bbbt *bbt;
++
++ struct dentry *debugfs_dir;
++
++ u32 pg_size;
++ u32 blk_size;
++ u16 pg_shift;
++ u16 blk_shift;
++ /* bbt logical address */
++ u16 pool_lba;
++ /* bbt physical address */
++ u16 pool_pba;
++ /* Maximum count of bad blocks that the vendor guaranteed */
++ u16 bb_max;
++ /* Total blocks of the Nand Chip */
++ u16 total_blks;
++ /* The block(n) BMT is located at (bmt_tbl[n]) */
++ u16 bmt_blk_idx;
++ /* How many pages needs to store 'struct bbbt' */
++ u32 bmt_pgs;
++
++ /* to compensate for driver level remapping */
++ u8 oob_offset;
++} bmtd = {0};
++
++static unsigned char *nand_bbt_buf;
++static unsigned char *nand_data_buf;
++
++/* -------- Unit conversions -------- */
++static inline u32 blk_pg(u16 block)
++{
++ return (u32)(block << (bmtd.blk_shift - bmtd.pg_shift));
++}
++
++/* -------- Nand operations wrapper -------- */
++static inline int
++bbt_nand_read(u32 page, unsigned char *dat, int dat_len,
++ unsigned char *fdm, int fdm_len)
++{
++ struct mtd_oob_ops ops = {
++ .mode = MTD_OPS_PLACE_OOB,
++ .ooboffs = bmtd.oob_offset,
++ .oobbuf = fdm,
++ .ooblen = fdm_len,
++ .datbuf = dat,
++ .len = dat_len,
++ };
++
++ return bmtd._read_oob(bmtd.mtd, page << bmtd.pg_shift, &ops);
++}
++
++static inline int bbt_nand_erase(u16 block)
++{
++ struct nand_device *nand = mtd_to_nanddev(bmtd.mtd);
++ loff_t addr = (loff_t)block << bmtd.blk_shift;
++ struct nand_pos pos;
++
++ nanddev_offs_to_pos(nand, addr, &pos);
++ return bmtd.nand_ops->erase(nand, &pos);
++}
++
++/* -------- Bad Blocks Management -------- */
++static int
++read_bmt(u16 block, unsigned char *dat, unsigned char *fdm, int fdm_len)
++{
++ u32 len = bmtd.bmt_pgs << bmtd.pg_shift;
++
++ return bbt_nand_read(blk_pg(block), dat, len, fdm, fdm_len);
++}
++
++static int write_bmt(u16 block, unsigned char *dat)
++{
++ struct mtd_oob_ops ops = {
++ .mode = MTD_OPS_PLACE_OOB,
++ .ooboffs = OOB_SIGNATURE_OFFSET + bmtd.oob_offset,
++ .oobbuf = "bmt",
++ .ooblen = 3,
++ .datbuf = dat,
++ .len = bmtd.bmt_pgs << bmtd.pg_shift,
++ };
++ loff_t addr = (loff_t)block << bmtd.blk_shift;
++
++ return bmtd._write_oob(bmtd.mtd, addr, &ops);
++}
++
++static u16 find_valid_block(u16 block)
++{
++ u8 fdm[4];
++ int ret;
++ int loop = 0;
++
++retry:
++ if (block >= bmtd.total_blks)
++ return 0;
++
++ ret = bbt_nand_read(blk_pg(block), nand_data_buf, bmtd.pg_size,
++ fdm, sizeof(fdm));
++ /* Read the 1st byte of FDM to judge whether it's a bad
++ * or not
++ */
++ if (ret || fdm[0] != 0xff) {
++ pr_info("nand: found bad block 0x%x\n", block);
++ if (loop >= bmtd.bb_max) {
++ pr_info("nand: FATAL ERR: too many bad blocks!!\n");
++ return 0;
++ }
++
++ loop++;
++ block++;
++ goto retry;
++ }
++
++ return block;
++}
++
++/* Find out all bad blocks, and fill in the mapping table */
++static int scan_bad_blocks(struct bbbt *bbt)
++{
++ int i;
++ u16 block = 0;
++
++ /* First time download, the block0 MUST NOT be a bad block,
++ * this is guaranteed by vendor
++ */
++ bbt->bb_tbl[0] = 0;
++
++ /*
++ * Construct the mapping table of Normal data area(non-PMT/BMTPOOL)
++ * G - Good block; B - Bad block
++ * ---------------------------
++ * physical |G|G|B|G|B|B|G|G|G|G|B|G|B|
++ * ---------------------------
++ * What bb_tbl[i] looks like:
++ * physical block(i):
++ * 0 1 2 3 4 5 6 7 8 9 a b c
++ * mapped block(bb_tbl[i]):
++ * 0 1 3 6 7 8 9 b ......
++ * ATTENTION:
++ * If new bad block ocurred(n), search bmt_tbl to find
++ * a available block(x), and fill in the bb_tbl[n] = x;
++ */
++ for (i = 1; i < bmtd.pool_lba; i++) {
++ bbt->bb_tbl[i] = find_valid_block(bbt->bb_tbl[i - 1] + 1);
++ BBT_LOG("bb_tbl[0x%x] = 0x%x", i, bbt->bb_tbl[i]);
++ if (bbt->bb_tbl[i] == 0)
++ return -1;
++ }
++
++ /* Physical Block start Address of BMT pool */
++ bmtd.pool_pba = bbt->bb_tbl[i - 1] + 1;
++ if (bmtd.pool_pba >= bmtd.total_blks - 2) {
++ pr_info("nand: FATAL ERR: Too many bad blocks!!\n");
++ return -1;
++ }
++
++ BBT_LOG("pool_pba=0x%x", bmtd.pool_pba);
++ i = 0;
++ block = bmtd.pool_pba;
++ /*
++ * The bmt table is used for runtime bad block mapping
++ * G - Good block; B - Bad block
++ * ---------------------------
++ * physical |G|G|B|G|B|B|G|G|G|G|B|G|B|
++ * ---------------------------
++ * block: 0 1 2 3 4 5 6 7 8 9 a b c
++ * What bmt_tbl[i] looks like in initial state:
++ * i:
++ * 0 1 2 3 4 5 6 7
++ * bmt_tbl[i].block:
++ * 0 1 3 6 7 8 9 b
++ * bmt_tbl[i].mapped:
++ * N N N N N N N B
++ * N - Not mapped(Available)
++ * M - Mapped
++ * B - BMT
++ * ATTENTION:
++ * BMT always in the last valid block in pool
++ */
++ while ((block = find_valid_block(block)) != 0) {
++ bbt->bmt_tbl[i].block = block;
++ bbt->bmt_tbl[i].mapped = NO_MAPPED;
++ BBT_LOG("bmt_tbl[%d].block = 0x%x", i, block);
++ block++;
++ i++;
++ }
++
++ /* i - How many available blocks in pool, which is the length of bmt_tbl[]
++ * bmtd.bmt_blk_idx - bmt_tbl[bmtd.bmt_blk_idx].block => the BMT block
++ */
++ bmtd.bmt_blk_idx = i - 1;
++ bbt->bmt_tbl[bmtd.bmt_blk_idx].mapped = BMT_MAPPED;
++
++ if (i < 1) {
++ pr_info("nand: FATAL ERR: no space to store BMT!!\n");
++ return -1;
++ }
++
++ pr_info("[BBT] %d available blocks in BMT pool\n", i);
++
++ return 0;
++}
++
++static bool is_valid_bmt(unsigned char *buf, unsigned char *fdm)
++{
++ struct bbbt *bbt = (struct bbbt *)buf;
++ u8 *sig = (u8*)bbt->signature + MAIN_SIGNATURE_OFFSET;
++
++
++ if (memcmp(bbt->signature + MAIN_SIGNATURE_OFFSET, "BMT", 3) == 0 &&
++ memcmp(fdm + OOB_SIGNATURE_OFFSET, "bmt", 3) == 0) {
++ if (bbt->version == BBMT_VERSION)
++ return true;
++ }
++ BBT_LOG("[BBT] BMT Version not match,upgrage preloader and uboot please! sig=%02x%02x%02x, fdm=%02x%02x%02x",
++ sig[0], sig[1], sig[2],
++ fdm[1], fdm[2], fdm[3]);
++ return false;
++}
++
++static u16 get_bmt_index(struct bbmt *bmt)
++{
++ int i = 0;
++
++ while (bmt[i].block != BMT_TBL_DEF_VAL) {
++ if (bmt[i].mapped == BMT_MAPPED)
++ return i;
++ i++;
++ }
++ return 0;
++}
++
++static struct bbbt *scan_bmt(u16 block)
++{
++ u8 fdm[4];
++
++ if (block < bmtd.pool_lba)
++ return NULL;
++
++ if (read_bmt(block, nand_bbt_buf, fdm, sizeof(fdm)))
++ return scan_bmt(block - 1);
++
++ if (is_valid_bmt(nand_bbt_buf, fdm)) {
++ bmtd.bmt_blk_idx = get_bmt_index(((struct bbbt *)nand_bbt_buf)->bmt_tbl);
++ if (bmtd.bmt_blk_idx == 0) {
++ pr_info("[BBT] FATAL ERR: bmt block index is wrong!\n");
++ return NULL;
++ }
++ pr_info("[BBT] BMT.v2 is found at 0x%x\n", block);
++ return (struct bbbt *)nand_bbt_buf;
++ } else
++ return scan_bmt(block - 1);
++}
++
++/* Write the Burner Bad Block Table to Nand Flash
++ * n - write BMT to bmt_tbl[n]
++ */
++static u16 upload_bmt(struct bbbt *bbt, int n)
++{
++ u16 block;
++
++retry:
++ if (n < 0 || bbt->bmt_tbl[n].mapped == NORMAL_MAPPED) {
++ pr_info("nand: FATAL ERR: no space to store BMT!\n");
++ return (u16)-1;
++ }
++
++ block = bbt->bmt_tbl[n].block;
++ BBT_LOG("n = 0x%x, block = 0x%x", n, block);
++ if (bbt_nand_erase(block)) {
++ bbt->bmt_tbl[n].block = 0;
++ /* erase failed, try the previous block: bmt_tbl[n - 1].block */
++ n--;
++ goto retry;
++ }
++
++ /* The signature offset is fixed set to 0,
++ * oob signature offset is fixed set to 1
++ */
++ memcpy(bbt->signature + MAIN_SIGNATURE_OFFSET, "BMT", 3);
++ bbt->version = BBMT_VERSION;
++
++ if (write_bmt(block, (unsigned char *)bbt)) {
++ bbt->bmt_tbl[n].block = 0;
++
++ /* write failed, try the previous block in bmt_tbl[n - 1] */
++ n--;
++ goto retry;
++ }
++
++ /* Return the current index(n) of BMT pool (bmt_tbl[n]) */
++ return n;
++}
++
++static u16 find_valid_block_in_pool(struct bbbt *bbt)
++{
++ int i;
++
++ if (bmtd.bmt_blk_idx == 0)
++ goto error;
++
++ for (i = 0; i < bmtd.bmt_blk_idx; i++) {
++ if (bbt->bmt_tbl[i].block != 0 && bbt->bmt_tbl[i].mapped == NO_MAPPED) {
++ bbt->bmt_tbl[i].mapped = NORMAL_MAPPED;
++ return bbt->bmt_tbl[i].block;
++ }
++ }
++
++error:
++ pr_info("nand: FATAL ERR: BMT pool is run out!\n");
++ return 0;
++}
++
++/* We met a bad block, mark it as bad and map it to a valid block in pool,
++ * if it's a write failure, we need to write the data to mapped block
++ */
++static bool update_bmt(u16 block)
++{
++ u16 mapped_blk;
++ struct bbbt *bbt;
++
++ bbt = bmtd.bbt;
++ mapped_blk = find_valid_block_in_pool(bbt);
++ if (mapped_blk == 0)
++ return false;
++
++ /* Map new bad block to available block in pool */
++ bbt->bb_tbl[block] = mapped_blk;
++ bmtd.bmt_blk_idx = upload_bmt(bbt, bmtd.bmt_blk_idx);
++
++ return true;
++}
++
++u16 get_mapping_block_index(int block)
++{
++ int mapping_block;
++
++ if (block < bmtd.pool_lba)
++ mapping_block = bmtd.bbt->bb_tbl[block];
++ else
++ mapping_block = block;
++ BBT_LOG("0x%x mapped to 0x%x", block, mapping_block);
++
++ return mapping_block;
++}
++
++static int
++mtk_bmt_read(struct mtd_info *mtd, loff_t from,
++ struct mtd_oob_ops *ops)
++{
++ struct mtd_oob_ops cur_ops = *ops;
++ int retry_count = 0;
++ loff_t cur_from;
++ int ret;
++
++ ops->retlen = 0;
++ ops->oobretlen = 0;
++
++ while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) {
++ u32 offset = from & (bmtd.blk_size - 1);
++ u32 block = from >> bmtd.blk_shift;
++ u32 cur_block;
++
++ cur_block = get_mapping_block_index(block);
++ cur_from = ((loff_t)cur_block << bmtd.blk_shift) + offset;
++
++ cur_ops.oobretlen = 0;
++ cur_ops.retlen = 0;
++ cur_ops.len = min_t(u32, mtd->erasesize - offset,
++ ops->len - ops->retlen);
++ ret = bmtd._read_oob(mtd, cur_from, &cur_ops);
++ if (ret < 0) {
++ update_bmt(block);
++ if (retry_count++ < 10)
++ continue;
++
++ return ret;
++ }
++
++ ops->retlen += cur_ops.retlen;
++ ops->oobretlen += cur_ops.oobretlen;
++
++ cur_ops.datbuf += cur_ops.retlen;
++ cur_ops.oobbuf += cur_ops.oobretlen;
++ cur_ops.ooblen -= cur_ops.oobretlen;
++
++ if (!cur_ops.len)
++ cur_ops.len = mtd->erasesize - offset;
++
++ from += cur_ops.len;
++ retry_count = 0;
++ }
++
++ return 0;
++}
++
++static int
++mtk_bmt_write(struct mtd_info *mtd, loff_t to,
++ struct mtd_oob_ops *ops)
++{
++ struct mtd_oob_ops cur_ops = *ops;
++ int retry_count = 0;
++ loff_t cur_to;
++ int ret;
++
++ ops->retlen = 0;
++ ops->oobretlen = 0;
++
++ while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) {
++ u32 offset = to & (bmtd.blk_size - 1);
++ u32 block = to >> bmtd.blk_shift;
++ u32 cur_block;
++
++ cur_block = get_mapping_block_index(block);
++ cur_to = ((loff_t)cur_block << bmtd.blk_shift) + offset;
++
++ cur_ops.oobretlen = 0;
++ cur_ops.retlen = 0;
++ cur_ops.len = min_t(u32, bmtd.blk_size - offset,
++ ops->len - ops->retlen);
++ ret = bmtd._write_oob(mtd, cur_to, &cur_ops);
++ if (ret < 0) {
++ update_bmt(block);
++ if (retry_count++ < 10)
++ continue;
++
++ return ret;
++ }
++
++ ops->retlen += cur_ops.retlen;
++ ops->oobretlen += cur_ops.oobretlen;
++
++ cur_ops.datbuf += cur_ops.retlen;
++ cur_ops.oobbuf += cur_ops.oobretlen;
++ cur_ops.ooblen -= cur_ops.oobretlen;
++
++ if (!cur_ops.len)
++ cur_ops.len = mtd->erasesize - offset;
++
++ to += cur_ops.len;
++ retry_count = 0;
++ }
++
++ return 0;
++}
++
++
++
++static int
++mtk_bmt_erase(struct nand_device *nand, const struct nand_pos *pos)
++{
++ struct nand_pos new_pos = *pos;
++ int retry_count = 0;
++ int ret;
++
++retry:
++ new_pos.eraseblock = get_mapping_block_index(pos->eraseblock);
++
++ ret = bmtd.nand_ops->erase(nand, &new_pos);
++ if (ret) {
++ update_bmt(pos->eraseblock);
++ if (retry_count++ < 10)
++ goto retry;
++ }
++
++ return ret;
++}
++
++static bool
++mtk_bmt_isbad(struct nand_device *nand, const struct nand_pos *pos)
++{
++ struct nand_pos new_pos = *pos;
++ int retry_count = 0;
++ bool ret;
++
++retry:
++ new_pos.eraseblock = get_mapping_block_index(pos->eraseblock);
++
++ ret = bmtd.nand_ops->isbad(nand, &new_pos);
++ if (ret) {
++ update_bmt(pos->eraseblock);
++ if (retry_count++ < 10)
++ goto retry;
++ }
++
++ return ret;
++}
++
++static int
++mtk_bmt_markbad(struct nand_device *nand, const struct nand_pos *pos)
++{
++ struct nand_pos new_pos = *pos;
++
++ new_pos.eraseblock = get_mapping_block_index(new_pos.eraseblock);
++ update_bmt(pos->eraseblock);
++
++ return bmtd.nand_ops->markbad(nand, &new_pos);
++}
++
++static void
++mtk_bmt_replace_ops(struct mtd_info *mtd)
++{
++ static const struct nand_ops mtk_bmt_nand_ops = {
++ .erase = mtk_bmt_erase,
++ .isbad = mtk_bmt_isbad,
++ .markbad = mtk_bmt_markbad,
++ };
++ struct nand_device *nand = mtd_to_nanddev(mtd);
++
++ bmtd.nand_ops = nand->ops;
++ bmtd._read_oob = mtd->_read_oob;
++ bmtd._write_oob = mtd->_write_oob;
++
++ mtd->_read_oob = mtk_bmt_read;
++ mtd->_write_oob = mtk_bmt_write;
++ nand->ops = &mtk_bmt_nand_ops;
++}
++
++static int mtk_bmt_debug_mark_good(void *data, u64 val)
++{
++ u32 block = val >> bmtd.blk_shift;
++
++ bmtd.bbt->bb_tbl[block] = block;
++ bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx);
++
++ return 0;
++}
++
++static int mtk_bmt_debug_mark_bad(void *data, u64 val)
++{
++ u32 block = val >> bmtd.blk_shift;
++
++ update_bmt(block);
++
++ return 0;
++}
++
++DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_good, NULL, mtk_bmt_debug_mark_good, "%llu\n");
++DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_bad, NULL, mtk_bmt_debug_mark_bad, "%llu\n");
++
++static void
++mtk_bmt_add_debugfs(void)
++{
++ struct dentry *dir;
++
++ dir = bmtd.debugfs_dir = debugfs_create_dir("mtk-bmt", NULL);
++ if (!dir)
++ return;
++
++ debugfs_create_file_unsafe("mark_good", S_IWUSR, dir, NULL, &fops_mark_good);
++ debugfs_create_file_unsafe("mark_bad", S_IWUSR, dir, NULL, &fops_mark_bad);
++}
++
++void mtk_bmt_detach(struct mtd_info *mtd)
++{
++ struct nand_device *nand = mtd_to_nanddev(mtd);
++
++ if (bmtd.mtd != mtd)
++ return;
++
++ if (bmtd.debugfs_dir)
++ debugfs_remove_recursive(bmtd.debugfs_dir);
++ bmtd.debugfs_dir = NULL;
++
++ kfree(nand_bbt_buf);
++ kfree(nand_data_buf);
++
++ mtd->_read_oob = bmtd._read_oob;
++ mtd->_write_oob = bmtd._write_oob;
++ mtd->size = bmtd.total_blks << bmtd.blk_shift;
++ nand->ops = bmtd.nand_ops;
++
++ memset(&bmtd, 0, sizeof(bmtd));
++}
++
++/* total_blocks - The total count of blocks that the Nand Chip has */
++int mtk_bmt_attach(struct mtd_info *mtd)
++{
++ struct device_node *np;
++ struct bbbt *bbt;
++ u32 bufsz;
++ u32 block;
++ u16 total_blocks, pmt_block;
++ int ret = 0;
++ u32 bmt_pool_size;
++
++ if (bmtd.mtd)
++ return -ENOSPC;
++
++ np = mtd_get_of_node(mtd);
++ if (!np)
++ return 0;
++
++ if (!of_property_read_bool(np, "mediatek,bmt-v2"))
++ return 0;
++
++ if (of_property_read_u32(np, "mediatek,bmt-pool-size",
++ &bmt_pool_size) != 0)
++ bmt_pool_size = 80;
++
++ if (of_property_read_u8(np, "mediatek,bmt-oob-offset",
++ &bmtd.oob_offset) != 0)
++ bmtd.oob_offset = 8;
++
++ bmtd.mtd = mtd;
++ mtk_bmt_replace_ops(mtd);
++
++ bmtd.blk_size = mtd->erasesize;
++ bmtd.blk_shift = ffs(bmtd.blk_size) - 1;
++ bmtd.pg_size = mtd->writesize;
++ bmtd.pg_shift = ffs(bmtd.pg_size) - 1;
++ total_blocks = mtd->size >> bmtd.blk_shift;
++ pmt_block = total_blocks - bmt_pool_size - 2;
++
++ mtd->size = pmt_block << bmtd.blk_shift;
++
++ /*
++ * ---------------------------------------
++ * | PMT(2blks) | BMT POOL(totalblks * 2%) |
++ * ---------------------------------------
++ * ^ ^
++ * | |
++ * pmt_block pmt_block + 2blocks(pool_lba)
++ *
++ * ATTETION!!!!!!
++ * The blocks ahead of the boundary block are stored in bb_tbl
++ * and blocks behind are stored in bmt_tbl
++ */
++
++ bmtd.pool_lba = (u16)(pmt_block + 2);
++ bmtd.total_blks = total_blocks;
++ bmtd.bb_max = bmtd.total_blks * BBPOOL_RATIO / 100;
++
++ /* 3 buffers we need */
++ bufsz = round_up(sizeof(struct bbbt), bmtd.pg_size);
++ bmtd.bmt_pgs = bufsz >> bmtd.pg_shift;
++
++ nand_bbt_buf = kzalloc(bufsz, GFP_KERNEL);
++ nand_data_buf = kzalloc(bmtd.pg_size, GFP_KERNEL);
++
++ if (!nand_bbt_buf || !nand_data_buf) {
++ pr_info("nand: FATAL ERR: allocate buffer failed!\n");
++ ret = -1;
++ goto error;
++ }
++
++ memset(nand_bbt_buf, 0xff, bufsz);
++ memset(nand_data_buf, 0xff, bmtd.pg_size);
++
++ BBT_LOG("bbtbuf=0x%p(0x%x) dat=0x%p(0x%x)",
++ nand_bbt_buf, bufsz, nand_data_buf, bmtd.pg_size);
++ BBT_LOG("pool_lba=0x%x total_blks=0x%x bb_max=0x%x",
++ bmtd.pool_lba, bmtd.total_blks, bmtd.bb_max);
++
++ /* Scanning start from the first page of the last block
++ * of whole flash
++ */
++ bbt = scan_bmt(bmtd.total_blks - 1);
++ if (!bbt) {
++ /* BMT not found */
++ if (bmtd.total_blks > BB_TABLE_MAX + BMT_TABLE_MAX) {
++ pr_info("nand: FATAL: Too many blocks, can not support!\n");
++ ret = -1;
++ goto error;
++ }
++
++ bbt = (struct bbbt *)nand_bbt_buf;
++ memset(bbt->bmt_tbl, BMT_TBL_DEF_VAL, sizeof(bbt->bmt_tbl));
++
++ if (scan_bad_blocks(bbt)) {
++ ret = -1;
++ goto error;
++ }
++
++ /* BMT always in the last valid block in pool */
++ bmtd.bmt_blk_idx = upload_bmt(bbt, bmtd.bmt_blk_idx);
++ block = bbt->bmt_tbl[bmtd.bmt_blk_idx].block;
++ pr_notice("[BBT] BMT.v2 is written into PBA:0x%x\n", block);
++
++ if (bmtd.bmt_blk_idx == 0)
++ pr_info("nand: Warning: no available block in BMT pool!\n");
++ else if (bmtd.bmt_blk_idx == (u16)-1) {
++ ret = -1;
++ goto error;
++ }
++ }
++ mtk_bmt_add_debugfs();
++
++ bmtd.bbt = bbt;
++ return 0;
++
++error:
++ mtk_bmt_detach(mtd);
++ return ret;
++}
++
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Xiangsheng Hou <xiangsheng.hou@mediatek.com>, Felix Fietkau <nbd@nbd.name>");
++MODULE_DESCRIPTION("Bad Block mapping management v2 for MediaTek NAND Flash Driver");
++
+--- a/drivers/mtd/nand/spi/core.c
++++ b/drivers/mtd/nand/spi/core.c
+@@ -19,6 +19,7 @@
+ #include <linux/string.h>
+ #include <linux/spi/spi.h>
+ #include <linux/spi/spi-mem.h>
++#include <linux/mtd/mtk_bmt.h>
+
+ static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val)
+ {
+@@ -1139,6 +1140,8 @@ static int spinand_probe(struct spi_mem
+ if (ret)
+ return ret;
+
++ mtk_bmt_attach(mtd);
++
+ ret = mtd_device_register(mtd, NULL, 0);
+ if (ret)
+ goto err_spinand_cleanup;
+@@ -1164,6 +1167,7 @@ static int spinand_remove(struct spi_mem
+ if (ret)
+ return ret;
+
++ mtk_bmt_detach(mtd);
+ spinand_cleanup(spinand);
+
+ return 0;
+--- /dev/null
++++ b/include/linux/mtd/mtk_bmt.h
+@@ -0,0 +1,18 @@
++#ifndef __MTK_BMT_H
++#define __MTK_BMT_H
++
++#ifdef CONFIG_MTD_NAND_MTK_BMT
++int mtk_bmt_attach(struct mtd_info *mtd);
++void mtk_bmt_detach(struct mtd_info *mtd);
++#else
++static inline int mtk_bmt_attach(struct mtd_info *mtd)
++{
++ return 0;
++}
++
++static inline void mtk_bmt_detach(struct mtd_info *mtd)
++{
++}
++#endif
++
++#endif
diff --git a/target/linux/mediatek/patches-5.10/400-crypto-add-eip97-inside-secure-support.patch b/target/linux/mediatek/patches-5.10/400-crypto-add-eip97-inside-secure-support.patch
new file mode 100644
index 0000000000..e0941a9550
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/400-crypto-add-eip97-inside-secure-support.patch
@@ -0,0 +1,27 @@
+--- a/drivers/crypto/inside-secure/safexcel.c
++++ b/drivers/crypto/inside-secure/safexcel.c
+@@ -600,6 +600,14 @@ static int safexcel_hw_init(struct safex
+ val |= EIP197_MST_CTRL_TX_MAX_CMD(5);
+ writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL);
+ }
++ /*
++ * Set maximum number of TX commands to 2^4 = 16 for EIP97 HW2.1/HW2.3
++ */
++ else {
++ val = 0;
++ val |= EIP97_MST_CTRL_TX_MAX_CMD(4);
++ writel(val, EIP197_HIA_AIC(priv) + EIP197_HIA_MST_CTRL);
++ }
+
+ /* Configure wr/rd cache values */
+ writel(EIP197_MST_CTRL_RD_CACHE(RD_CACHE_4BITS) |
+--- a/drivers/crypto/inside-secure/safexcel.h
++++ b/drivers/crypto/inside-secure/safexcel.h
+@@ -314,6 +314,7 @@
+ #define EIP197_MST_CTRL_RD_CACHE(n) (((n) & 0xf) << 0)
+ #define EIP197_MST_CTRL_WD_CACHE(n) (((n) & 0xf) << 4)
+ #define EIP197_MST_CTRL_TX_MAX_CMD(n) (((n) & 0xf) << 20)
++#define EIP97_MST_CTRL_TX_MAX_CMD(n) (((n) & 0xf) << 4)
+ #define EIP197_MST_CTRL_BYTE_SWAP BIT(24)
+ #define EIP197_MST_CTRL_NO_BYTE_SWAP BIT(25)
+ #define EIP197_MST_CTRL_BYTE_SWAP_BITS GENMASK(25, 24)
diff --git a/target/linux/mediatek/patches-5.10/401-crypto-fix-eip97-cache-incoherent.patch b/target/linux/mediatek/patches-5.10/401-crypto-fix-eip97-cache-incoherent.patch
new file mode 100644
index 0000000000..be2bffb749
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/401-crypto-fix-eip97-cache-incoherent.patch
@@ -0,0 +1,26 @@
+--- a/drivers/crypto/inside-secure/safexcel.h
++++ b/drivers/crypto/inside-secure/safexcel.h
+@@ -736,6 +736,9 @@ enum safexcel_eip_version {
+ /* Priority we use for advertising our algorithms */
+ #define SAFEXCEL_CRA_PRIORITY 300
+
++/* System cache line size */
++#define SYSTEM_CACHELINE_SIZE 64
++
+ /* SM3 digest result for zero length message */
+ #define EIP197_SM3_ZEROM_HASH "\x1A\xB2\x1D\x83\x55\xCF\xA1\x7F" \
+ "\x8E\x61\x19\x48\x31\xE8\x1A\x8F" \
+--- a/drivers/crypto/inside-secure/safexcel_hash.c
++++ b/drivers/crypto/inside-secure/safexcel_hash.c
+@@ -53,9 +53,9 @@ struct safexcel_ahash_req {
+ u8 block_sz; /* block size, only set once */
+ u8 digest_sz; /* output digest size, only set once */
+ __le32 state[SHA3_512_BLOCK_SIZE /
+- sizeof(__le32)] __aligned(sizeof(__le32));
++ sizeof(__le32)] __aligned(SYSTEM_CACHELINE_SIZE);
+
+- u64 len;
++ u64 len __aligned(SYSTEM_CACHELINE_SIZE);
+ u64 processed;
+
+ u8 cache[HASH_CACHE_SIZE] __aligned(sizeof(u32));
diff --git a/target/linux/mediatek/patches-5.10/410-bt-mtk-serial-fix.patch b/target/linux/mediatek/patches-5.10/410-bt-mtk-serial-fix.patch
new file mode 100644
index 0000000000..2e474dd5fe
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/410-bt-mtk-serial-fix.patch
@@ -0,0 +1,33 @@
+--- a/drivers/tty/serial/8250/8250.h
++++ b/drivers/tty/serial/8250/8250.h
+@@ -82,6 +82,7 @@ struct serial8250_config {
+ #define UART_CAP_MINI (1 << 17) /* Mini UART on BCM283X family lacks:
+ * STOP PARITY EPAR SPAR WLEN5 WLEN6
+ */
++#define UART_CAP_NMOD (1 << 18) /* UART doesn't do termios */
+
+ #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */
+ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -287,7 +287,7 @@ static const struct serial8250_config ua
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
+- .flags = UART_CAP_FIFO,
++ .flags = UART_CAP_FIFO | UART_CAP_NMOD,
+ },
+ [PORT_NPCM] = {
+ .name = "Nuvoton 16550",
+@@ -2687,6 +2687,11 @@ serial8250_do_set_termios(struct uart_po
+ unsigned long flags;
+ unsigned int baud, quot, frac = 0;
+
++ if (up->capabilities & UART_CAP_NMOD) {
++ termios->c_cflag = 0;
++ return;
++ }
++
+ if (up->capabilities & UART_CAP_MINI) {
+ termios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CMSPAR);
+ if ((termios->c_cflag & CSIZE) == CS5 ||
diff --git a/target/linux/mediatek/patches-5.10/500-gsw-rtl8367s-mt7622-support.patch b/target/linux/mediatek/patches-5.10/500-gsw-rtl8367s-mt7622-support.patch
new file mode 100644
index 0000000000..bdd482def3
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/500-gsw-rtl8367s-mt7622-support.patch
@@ -0,0 +1,25 @@
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -334,6 +334,12 @@ config ROCKCHIP_PHY
+ help
+ Currently supports the integrated Ethernet PHY.
+
++config RTL8367S_GSW
++ tristate "rtl8367 Gigabit Switch support for mt7622"
++ depends on NET_VENDOR_MEDIATEK
++ help
++ This driver supports rtl8367s in mt7622
++
+ config SMSC_PHY
+ tristate "SMSC PHYs"
+ help
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -88,6 +88,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
+ obj-$(CONFIG_REALTEK_PHY) += realtek.o
+ obj-$(CONFIG_RENESAS_PHY) += uPD60620.o
+ obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o
++obj-$(CONFIG_RTL8367S_GSW) += rtk/
+ obj-$(CONFIG_SMSC_PHY) += smsc.o
+ obj-$(CONFIG_STE10XP) += ste10Xp.o
+ obj-$(CONFIG_TERANETICS_PHY) += teranetics.o
diff --git a/target/linux/mediatek/patches-5.10/600-dt-bindings-PCI-Mediatek-Update-PCIe-binding.patch b/target/linux/mediatek/patches-5.10/600-dt-bindings-PCI-Mediatek-Update-PCIe-binding.patch
new file mode 100644
index 0000000000..02e4c130ea
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/600-dt-bindings-PCI-Mediatek-Update-PCIe-binding.patch
@@ -0,0 +1,415 @@
+From patchwork Thu May 28 06:16:45 2020
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Chuanjia Liu <chuanjia.liu@mediatek.com>
+X-Patchwork-Id: 11574793
+Return-Path:
+ <SRS0=ftSA=7K=lists.infradead.org=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@kernel.org>
+Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org
+ [172.30.200.123])
+ by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 391201392
+ for <patchwork-linux-mediatek@patchwork.kernel.org>;
+ Thu, 28 May 2020 06:20:27 +0000 (UTC)
+Received: from bombadil.infradead.org (bombadil.infradead.org
+ [198.137.202.133])
+ (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
+ (No client certificate requested)
+ by mail.kernel.org (Postfix) with ESMTPS id 104F620657
+ for <patchwork-linux-mediatek@patchwork.kernel.org>;
+ Thu, 28 May 2020 06:20:27 +0000 (UTC)
+Authentication-Results: mail.kernel.org;
+ dkim=pass (2048-bit key) header.d=lists.infradead.org
+ header.i=@lists.infradead.org header.b="raZHaWxs";
+ dkim=fail reason="signature verification failed" (1024-bit key)
+ header.d=mediatek.com header.i=@mediatek.com header.b="YztrByG/"
+DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 104F620657
+Authentication-Results: mail.kernel.org;
+ dmarc=fail (p=none dis=none) header.from=mediatek.com
+Authentication-Results: mail.kernel.org;
+ spf=none
+ smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
+ d=lists.infradead.org; s=bombadil.20170209; h=Sender:
+ Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:
+ List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:
+ Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description:
+ Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
+ List-Owner; bh=aVtKU+Ey8KEM97+S66fz9ZMo+H8BP570jhAAvaRsNWc=; b=raZHaWxsfCxsrd
+ Byn/w1oLN/J82ApnNdBBXixq9Qj0uXIU2tBVqkiQ9lG6QDk7uguxQSJLeTqrsI/uxQmCI/PGQtZdP
+ sH0oboi2sbQSqJ/1ud4uL2pPaiLRJCxINF5oWjoZMsjn/b2fWvn52P6vTr/dxDTaabiVhY0HL0J+X
+ 7YGc1aYtO76HZHE2ke3puR42QkI8hE9E2cEhiLWeuUiLdUBegNM5MdYftu4nJTcCXnAeJjp/wIpYG
+ 7X737N9cmanDf6Bxr2bNPgaYzH+m7JK6eGxuAvWo0+PE9OX7MLrXY3KjixcjD/b0he0mfEM++gBAq
+ KBYKl5wh1mnlR2WIWXew==;
+Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org)
+ by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux))
+ id 1jeBtx-0005JC-DJ; Thu, 28 May 2020 06:20:25 +0000
+Received: from mailgw01.mediatek.com ([216.200.240.184])
+ by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux))
+ id 1jeBtW-0002f2-75; Thu, 28 May 2020 06:20:01 +0000
+X-UUID: d5cb6d96c2a5421796c2f8a284ff3670-20200527
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
+ d=mediatek.com;
+ s=dk;
+ h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From;
+ bh=EqjC+5cHgv6eykN7FPf2mtwK9UivJ3XSCE0jEvb8h+8=;
+ b=YztrByG/Ia304l9KDPBwoHFYkFCN6qBXPqwZgg56CA9VitadAg2+K1VgfEU+oHqsqcsGAMdZTRMQh17tpm4bJParw6MMzAQ28te2TcxvQMV8PZMkerJdZyyYblI7ybauPWuofAQgQMtuwSKVii8eTRJbf99OZ9vDGJP3zo2j1wU=;
+X-UUID: d5cb6d96c2a5421796c2f8a284ff3670-20200527
+Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by
+ mailgw01.mediatek.com
+ (envelope-from <chuanjia.liu@mediatek.com>)
+ (musrelay.mediatek.com ESMTP with TLS)
+ with ESMTP id 681958707; Wed, 27 May 2020 22:20:16 -0800
+Received: from MTKMBS07N2.mediatek.inc (172.21.101.141) by
+ MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id
+ 15.0.1497.2; Wed, 27 May 2020 23:18:52 -0700
+Received: from mtkcas07.mediatek.inc (172.21.101.84) by
+ mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id
+ 15.0.1497.2; Thu, 28 May 2020 14:18:49 +0800
+Received: from localhost.localdomain (10.17.3.153) by mtkcas07.mediatek.inc
+ (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend
+ Transport; Thu, 28 May 2020 14:18:47 +0800
+From: <chuanjia.liu@mediatek.com>
+To: <robh+dt@kernel.org>, <ryder.lee@mediatek.com>, <matthias.bgg@gmail.com>
+Subject: [PATCH v2 1/4] dt-bindings: PCI: Mediatek: Update PCIe binding
+Date: Thu, 28 May 2020 14:16:45 +0800
+Message-ID: <20200528061648.32078-2-chuanjia.liu@mediatek.com>
+X-Mailer: git-send-email 2.18.0
+In-Reply-To: <20200528061648.32078-1-chuanjia.liu@mediatek.com>
+References: <20200528061648.32078-1-chuanjia.liu@mediatek.com>
+MIME-Version: 1.0
+X-MTK: N
+X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3
+X-CRM114-CacheID: sfid-20200527_231958_261064_608CC03E
+X-CRM114-Status: GOOD ( 13.95 )
+X-Spam-Score: -0.2 (/)
+X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary:
+ Content analysis details: (-0.2 points)
+ pts rule name description
+ ---- ----------------------
+ --------------------------------------------------
+ -0.0 SPF_PASS SPF: sender matches SPF record
+ 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record
+ 0.0 MIME_BASE64_TEXT RAW: Message text disguised using base64
+ encoding
+ -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from
+ author's domain
+ 0.1 DKIM_SIGNED Message has a DKIM or DK signature,
+ not necessarily
+ valid
+ -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature
+ -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from
+ envelope-from domain
+ 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay
+ lines
+X-BeenThere: linux-mediatek@lists.infradead.org
+X-Mailman-Version: 2.1.29
+Precedence: list
+List-Id: <linux-mediatek.lists.infradead.org>
+List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-mediatek>,
+ <mailto:linux-mediatek-request@lists.infradead.org?subject=unsubscribe>
+List-Archive: <http://lists.infradead.org/pipermail/linux-mediatek/>
+List-Post: <mailto:linux-mediatek@lists.infradead.org>
+List-Help: <mailto:linux-mediatek-request@lists.infradead.org?subject=help>
+List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-mediatek>,
+ <mailto:linux-mediatek-request@lists.infradead.org?subject=subscribe>
+Cc: devicetree@vger.kernel.org, lorenzo.pieralisi@arm.com,
+ srv_heupstream@mediatek.com, "chuanjia.liu" <Chuanjia.Liu@mediatek.com>,
+ linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
+ jianjun.wang@mediatek.com, linux-mediatek@lists.infradead.org,
+ yong.wu@mediatek.com, bhelgaas@google.com,
+ linux-arm-kernel@lists.infradead.org, amurray@thegoodpenguin.co.uk
+Sender: "Linux-mediatek" <linux-mediatek-bounces@lists.infradead.org>
+Errors-To:
+ linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org
+
+From: "chuanjia.liu" <Chuanjia.Liu@mediatek.com>
+
+There are two independent PCIe controllers in MT2712/MT7622 platform,
+and each of them should contain an independent MSI domain.
+
+In current architecture, MSI domain will be inherited from the root
+bridge, and all of the devices will share the same MSI domain.
+Hence that, the PCIe devices will not work properly if the irq number
+which required is more than 32.
+
+Split the PCIe node for MT2712/MT7622 platform to fix MSI issue and
+comply with the hardware design.
+
+Signed-off-by: chuanjia.liu <Chuanjia.Liu@mediatek.com>
+---
+ .../bindings/pci/mediatek-pcie-cfg.yaml | 38 +++++
+ .../devicetree/bindings/pci/mediatek-pcie.txt | 144 +++++++++++-------
+ 2 files changed, 129 insertions(+), 53 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/pci/mediatek-pcie-cfg.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pci/mediatek-pcie-cfg.yaml
+@@ -0,0 +1,38 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/pci/mediatek-pcie-cfg.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: Mediatek PCIECFG controller
++
++maintainers:
++ - Chuanjia Liu <chuanjia.liu@mediatek.com>
++ - Jianjun Wang <jianjun.wang@mediatek.com>
++
++description: |
++ The MediaTek PCIECFG controller controls some feature about
++ LTSSM, ASPM and so on.
++
++properties:
++ compatible:
++ items:
++ - enum:
++ - mediatek,mt7622-pciecfg
++ - mediatek,mt7629-pciecfg
++ - const: syscon
++
++ reg:
++ maxItems: 1
++
++required:
++ - compatible
++ - reg
++
++examples:
++ - |
++ pciecfg: pciecfg@1a140000 {
++ compatible = "mediatek,mt7622-pciecfg", "syscon";
++ reg = <0 0x1a140000 0 0x1000>;
++ };
++...
+--- a/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
++++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt
+@@ -8,7 +8,7 @@ Required properties:
+ "mediatek,mt7623-pcie"
+ "mediatek,mt7629-pcie"
+ - device_type: Must be "pci"
+-- reg: Base addresses and lengths of the PCIe subsys and root ports.
++- reg: Base addresses and lengths of the root ports.
+ - reg-names: Names of the above areas to use during resource lookup.
+ - #address-cells: Address representation for root ports (must be 3)
+ - #size-cells: Size representation for root ports (must be 2)
+@@ -19,10 +19,10 @@ Required properties:
+ - sys_ckN :transaction layer and data link layer clock
+ Required entries for MT2701/MT7623:
+ - free_ck :for reference clock of PCIe subsys
+- Required entries for MT2712/MT7622:
++ Required entries for MT2712/MT7622/MT7629:
+ - ahb_ckN :AHB slave interface operating clock for CSR access and RC
+ initiated MMIO access
+- Required entries for MT7622:
++ Required entries for MT7622/MT7629:
+ - axi_ckN :application layer MMIO channel operating clock
+ - aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
+ pcie_mac_ck/pcie_pipe_ck is turned off
+@@ -47,10 +47,13 @@ Required properties for MT7623/MT2701:
+ - reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
+ number of root ports.
+
+-Required properties for MT2712/MT7622:
++Required properties for MT2712/MT7622/MT7629:
+ -interrupts: A list of interrupt outputs of the controller, must have one
+ entry for each PCIe port
+
++Required properties for MT7622/MT7629:
++- mediatek,pcie-subsys: Should be a phandle of the pciecfg node.
++
+ In addition, the device tree node must have sub-nodes describing each
+ PCIe port interface, having the following mandatory properties:
+
+@@ -143,56 +146,73 @@ Examples for MT7623:
+
+ Examples for MT2712:
+
+- pcie: pcie@11700000 {
++ pcie1: pcie@112ff000 {
+ compatible = "mediatek,mt2712-pcie";
+ device_type = "pci";
+- reg = <0 0x11700000 0 0x1000>,
+- <0 0x112ff000 0 0x1000>;
+- reg-names = "port0", "port1";
++ reg = <0 0x112ff000 0 0x1000>;
++ reg-names = "port1";
+ #address-cells = <3>;
+ #size-cells = <2>;
+- interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+- clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
+- <&topckgen CLK_TOP_PE2_MAC_P1_SEL>,
+- <&pericfg CLK_PERI_PCIE0>,
++ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "pcie_irq";
++ clocks = <&topckgen CLK_TOP_PE2_MAC_P1_SEL>,
+ <&pericfg CLK_PERI_PCIE1>;
+- clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
+- phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
+- phy-names = "pcie-phy0", "pcie-phy1";
++ clock-names = "sys_ck1", "ahb_ck1";
++ phys = <&u3port1 PHY_TYPE_PCIE>;
++ phy-names = "pcie-phy1";
+ bus-range = <0x00 0xff>;
+- ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>;
++ ranges = <0x82000000 0 0x11400000 0x0 0x11400000 0 0x300000>;
++ status = "disabled";
+
+- pcie0: pcie@0,0 {
+- reg = <0x0000 0 0 0 0>;
++ slot1: pcie@1,0 {
++ reg = <0x0800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+ interrupt-map-mask = <0 0 0 7>;
+- interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+- <0 0 0 2 &pcie_intc0 1>,
+- <0 0 0 3 &pcie_intc0 2>,
+- <0 0 0 4 &pcie_intc0 3>;
+- pcie_intc0: interrupt-controller {
++ interrupt-map = <0 0 0 1 &pcie_intc1 0>,
++ <0 0 0 2 &pcie_intc1 1>,
++ <0 0 0 3 &pcie_intc1 2>,
++ <0 0 0 4 &pcie_intc1 3>;
++ pcie_intc1: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
++ };
+
+- pcie1: pcie@1,0 {
+- reg = <0x0800 0 0 0 0>;
++ pcie0: pcie@11700000 {
++ compatible = "mediatek,mt2712-pcie";
++ device_type = "pci";
++ reg = <0 0x11700000 0 0x1000>;
++ reg-names = "port0";
++ #address-cells = <3>;
++ #size-cells = <2>;
++ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "pcie_irq";
++ clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
++ <&pericfg CLK_PERI_PCIE0>;
++ clock-names = "sys_ck0", "ahb_ck0";
++ phys = <&u3port0 PHY_TYPE_PCIE>;
++ phy-names = "pcie-phy0";
++ bus-range = <0x00 0xff>;
++ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>;
++ status = "disabled";
++
++ slot0: pcie@0,0 {
++ reg = <0x0000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+ interrupt-map-mask = <0 0 0 7>;
+- interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+- <0 0 0 2 &pcie_intc1 1>,
+- <0 0 0 3 &pcie_intc1 2>,
+- <0 0 0 4 &pcie_intc1 3>;
+- pcie_intc1: interrupt-controller {
++ interrupt-map = <0 0 0 1 &pcie_intc0 0>,
++ <0 0 0 2 &pcie_intc0 1>,
++ <0 0 0 3 &pcie_intc0 2>,
++ <0 0 0 4 &pcie_intc0 3>;
++ pcie_intc0: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+@@ -202,39 +222,31 @@ Examples for MT2712:
+
+ Examples for MT7622:
+
+- pcie: pcie@1a140000 {
++ pcie0: pcie@1a143000 {
+ compatible = "mediatek,mt7622-pcie";
+ device_type = "pci";
+- reg = <0 0x1a140000 0 0x1000>,
+- <0 0x1a143000 0 0x1000>,
+- <0 0x1a145000 0 0x1000>;
+- reg-names = "subsys", "port0", "port1";
++ reg = <0 0x1a143000 0 0x1000>;
++ reg-names = "port0";
++ mediatek,pcie-cfg = <&pciecfg>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+- interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
+- <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
++ interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>;
++ interrupt-names = "pcie_irq";
+ clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
+- <&pciesys CLK_PCIE_P1_MAC_EN>,
+ <&pciesys CLK_PCIE_P0_AHB_EN>,
+- <&pciesys CLK_PCIE_P1_AHB_EN>,
+ <&pciesys CLK_PCIE_P0_AUX_EN>,
+- <&pciesys CLK_PCIE_P1_AUX_EN>,
+ <&pciesys CLK_PCIE_P0_AXI_EN>,
+- <&pciesys CLK_PCIE_P1_AXI_EN>,
+ <&pciesys CLK_PCIE_P0_OBFF_EN>,
+- <&pciesys CLK_PCIE_P1_OBFF_EN>,
+- <&pciesys CLK_PCIE_P0_PIPE_EN>,
+- <&pciesys CLK_PCIE_P1_PIPE_EN>;
+- clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
+- "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
+- "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
+- phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
+- phy-names = "pcie-phy0", "pcie-phy1";
++ <&pciesys CLK_PCIE_P0_PIPE_EN>;
++ clock-names = "sys_ck0", "ahb_ck0", "aux_ck0",
++ "axi_ck0", "obff_ck0", "pipe_ck0";
++
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+ bus-range = <0x00 0xff>;
+- ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>;
++ ranges = <0x82000000 0 0x20000000 0 0x20000000 0 0x8000000>;
++ status = "disabled";
+
+- pcie0: pcie@0,0 {
++ slot0: pcie@0,0 {
+ reg = <0x0000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+@@ -251,8 +263,34 @@ Examples for MT7622:
+ #interrupt-cells = <1>;
+ };
+ };
++ };
++
++ pcie1: pcie@1a145000 {
++ compatible = "mediatek,mt7622-pcie";
++ device_type = "pci";
++ reg = <0 0x1a145000 0 0x1000>;
++ reg-names = "port1";
++ mediatek,pcie-cfg = <&pciecfg>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
++ interrupt-names = "pcie_irq";
++ clocks = <&pciesys CLK_PCIE_P1_MAC_EN>,
++ /* designer has connect RC1 with p0_ahb clock */
++ <&pciesys CLK_PCIE_P0_AHB_EN>,
++ <&pciesys CLK_PCIE_P1_AUX_EN>,
++ <&pciesys CLK_PCIE_P1_AXI_EN>,
++ <&pciesys CLK_PCIE_P1_OBFF_EN>,
++ <&pciesys CLK_PCIE_P1_PIPE_EN>;
++ clock-names = "sys_ck1", "ahb_ck1", "aux_ck1",
++ "axi_ck1", "obff_ck1", "pipe_ck1";
++
++ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
++ bus-range = <0x00 0xff>;
++ ranges = <0x82000000 0 0x28000000 0 0x28000000 0 0x8000000>;
++ status = "disabled";
+
+- pcie1: pcie@1,0 {
++ slot1: pcie@1,0 {
+ reg = <0x0800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
diff --git a/target/linux/mediatek/patches-5.10/601-PCI-mediatek-Use-regmap-to-get-shared-pcie-cfg-base.patch b/target/linux/mediatek/patches-5.10/601-PCI-mediatek-Use-regmap-to-get-shared-pcie-cfg-base.patch
new file mode 100644
index 0000000000..9c18565319
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/601-PCI-mediatek-Use-regmap-to-get-shared-pcie-cfg-base.patch
@@ -0,0 +1,217 @@
+From patchwork Thu May 28 06:16:46 2020
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Chuanjia Liu <chuanjia.liu@mediatek.com>
+X-Patchwork-Id: 11574781
+Return-Path:
+ <SRS0=ftSA=7K=lists.infradead.org=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@kernel.org>
+Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org
+ [172.30.200.123])
+ by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0A99B60D
+ for <patchwork-linux-mediatek@patchwork.kernel.org>;
+ Thu, 28 May 2020 06:19:04 +0000 (UTC)
+Received: from bombadil.infradead.org (bombadil.infradead.org
+ [198.137.202.133])
+ (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
+ (No client certificate requested)
+ by mail.kernel.org (Postfix) with ESMTPS id DCC99208FE
+ for <patchwork-linux-mediatek@patchwork.kernel.org>;
+ Thu, 28 May 2020 06:19:03 +0000 (UTC)
+Authentication-Results: mail.kernel.org;
+ dkim=pass (2048-bit key) header.d=lists.infradead.org
+ header.i=@lists.infradead.org header.b="SpOi0ueF";
+ dkim=fail reason="signature verification failed" (1024-bit key)
+ header.d=mediatek.com header.i=@mediatek.com header.b="UGIBoIEG"
+DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org DCC99208FE
+Authentication-Results: mail.kernel.org;
+ dmarc=fail (p=none dis=none) header.from=mediatek.com
+Authentication-Results: mail.kernel.org;
+ spf=none
+ smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
+ d=lists.infradead.org; s=bombadil.20170209; h=Sender:
+ Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:
+ List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:
+ Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description:
+ Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
+ List-Owner; bh=LIr5poLUT/UdH6/akh/pnICGGa3rUBkN+4FhE1DyOrU=; b=SpOi0ueFcoJ/ka
+ 4esa6cDd5oU4fp0z684ZVPaVvvhm/azSZBBMYinHaAW6EvzKcMNYIX9grP8eg/728lEPNTKVq0I8H
+ PQZ9KvD4uTu8Opo1hD8LsRSLr+YLpNKt3KPOY/4gpwQ97uU9rI5PwkuAxPBgR949Vh5EiG0Vaww1H
+ Ep+I5BFRn2LVVQZP1Z7U0A0VUcOTLJ4znoWRLEXxtM9/Wd4hwQsrEPQszeDFti/RbwGfJ5efOb5UL
+ fhwBzSxELEzAAgH7env/XD2sSSpVf2Qsn6WO8D3ZepMtWrRtARiaRKSNxSBQTg2SSHcjmBSJSzcX+
+ w8wqWaUMs0crlBuZWS1g==;
+Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org)
+ by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux))
+ id 1jeBsc-0001tI-88; Thu, 28 May 2020 06:19:02 +0000
+Received: from mailgw01.mediatek.com ([216.200.240.184])
+ by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux))
+ id 1jeBsZ-0001rp-6g; Thu, 28 May 2020 06:19:01 +0000
+X-UUID: beeaf5765357439c91eab1f67ca7ef43-20200527
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
+ d=mediatek.com;
+ s=dk;
+ h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From;
+ bh=+IjWjsF/DhknqZB+lLSZ50cyvxDap+8w4tvqhp8Dv68=;
+ b=UGIBoIEGJUuq5pEvYEad1HVGpiv6yma+94hva83D2gD8lYmihRWkpJxB2yn+dVtNm7ZXXoQBf+jvvULOmslJgs1HZTLJTnjpdvLmQqo42OXRXSVpTE49HdRkJZDAIWIAReBfOEkFgNxcIX3uedrtnww/NLJ2lagrYPG5ET4lI2E=;
+X-UUID: beeaf5765357439c91eab1f67ca7ef43-20200527
+Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw01.mediatek.com
+ (envelope-from <chuanjia.liu@mediatek.com>)
+ (musrelay.mediatek.com ESMTP with TLS)
+ with ESMTP id 603406343; Wed, 27 May 2020 22:19:17 -0800
+Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by
+ MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id
+ 15.0.1497.2; Wed, 27 May 2020 23:18:47 -0700
+Received: from mtkcas07.mediatek.inc (172.21.101.84) by
+ mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id
+ 15.0.1497.2; Thu, 28 May 2020 14:18:51 +0800
+Received: from localhost.localdomain (10.17.3.153) by mtkcas07.mediatek.inc
+ (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend
+ Transport; Thu, 28 May 2020 14:18:49 +0800
+From: <chuanjia.liu@mediatek.com>
+To: <robh+dt@kernel.org>, <ryder.lee@mediatek.com>, <matthias.bgg@gmail.com>
+Subject: [PATCH v2 2/4] PCI: mediatek: Use regmap to get shared pcie-cfg base
+Date: Thu, 28 May 2020 14:16:46 +0800
+Message-ID: <20200528061648.32078-3-chuanjia.liu@mediatek.com>
+X-Mailer: git-send-email 2.18.0
+In-Reply-To: <20200528061648.32078-1-chuanjia.liu@mediatek.com>
+References: <20200528061648.32078-1-chuanjia.liu@mediatek.com>
+MIME-Version: 1.0
+X-MTK: N
+X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3
+X-CRM114-CacheID: sfid-20200527_231859_251275_BED2B1E2
+X-CRM114-Status: GOOD ( 11.62 )
+X-Spam-Score: -0.2 (/)
+X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary:
+ Content analysis details: (-0.2 points)
+ pts rule name description
+ ---- ----------------------
+ --------------------------------------------------
+ -0.0 SPF_PASS SPF: sender matches SPF record
+ 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record
+ 0.0 MIME_BASE64_TEXT RAW: Message text disguised using base64
+ encoding
+ -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from
+ author's domain
+ 0.1 DKIM_SIGNED Message has a DKIM or DK signature,
+ not necessarily
+ valid
+ -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature
+ -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from
+ envelope-from domain
+ 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay
+ lines
+X-BeenThere: linux-mediatek@lists.infradead.org
+X-Mailman-Version: 2.1.29
+Precedence: list
+List-Id: <linux-mediatek.lists.infradead.org>
+List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-mediatek>,
+ <mailto:linux-mediatek-request@lists.infradead.org?subject=unsubscribe>
+List-Archive: <http://lists.infradead.org/pipermail/linux-mediatek/>
+List-Post: <mailto:linux-mediatek@lists.infradead.org>
+List-Help: <mailto:linux-mediatek-request@lists.infradead.org?subject=help>
+List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-mediatek>,
+ <mailto:linux-mediatek-request@lists.infradead.org?subject=subscribe>
+Cc: devicetree@vger.kernel.org, lorenzo.pieralisi@arm.com,
+ srv_heupstream@mediatek.com, "chuanjia.liu" <Chuanjia.Liu@mediatek.com>,
+ linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
+ jianjun.wang@mediatek.com, linux-mediatek@lists.infradead.org,
+ yong.wu@mediatek.com, bhelgaas@google.com,
+ linux-arm-kernel@lists.infradead.org, amurray@thegoodpenguin.co.uk
+Sender: "Linux-mediatek" <linux-mediatek-bounces@lists.infradead.org>
+Errors-To:
+ linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org
+
+From: "chuanjia.liu" <Chuanjia.Liu@mediatek.com>
+
+Use regmap to get shared pcie-cfg base and change
+the method to get pcie irq.
+
+Signed-off-by: chuanjia.liu <Chuanjia.Liu@mediatek.com>
+---
+ drivers/pci/controller/pcie-mediatek.c | 25 ++++++++++++++++++-------
+ 1 file changed, 18 insertions(+), 7 deletions(-)
+
+--- a/drivers/pci/controller/pcie-mediatek.c
++++ b/drivers/pci/controller/pcie-mediatek.c
+@@ -14,6 +14,7 @@
+ #include <linux/irqchip/chained_irq.h>
+ #include <linux/irqdomain.h>
+ #include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
+ #include <linux/msi.h>
+ #include <linux/module.h>
+ #include <linux/of_address.h>
+@@ -23,6 +24,7 @@
+ #include <linux/phy/phy.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_runtime.h>
++#include <linux/regmap.h>
+ #include <linux/reset.h>
+
+ #include "../pci.h"
+@@ -205,6 +207,7 @@ struct mtk_pcie_port {
+ * struct mtk_pcie - PCIe host information
+ * @dev: pointer to PCIe device
+ * @base: IO mapped register base
++ * @cfg: IO mapped register map for PCIe config
+ * @free_ck: free-run reference clock
+ * @mem: non-prefetchable memory resource
+ * @ports: pointer to PCIe port information
+@@ -213,6 +216,7 @@ struct mtk_pcie_port {
+ struct mtk_pcie {
+ struct device *dev;
+ void __iomem *base;
++ struct regmap *cfg;
+ struct clk *free_ck;
+
+ struct list_head ports;
+@@ -648,7 +652,7 @@ static int mtk_pcie_setup_irq(struct mtk
+ return err;
+ }
+
+- port->irq = platform_get_irq(pdev, port->slot);
++ port->irq = platform_get_irq_byname(pdev, "pcie_irq");
+ if (port->irq < 0)
+ return port->irq;
+
+@@ -674,12 +678,11 @@ static int mtk_pcie_startup_port_v2(stru
+ if (!mem)
+ return -EINVAL;
+
+- /* MT7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
+- if (pcie->base) {
+- val = readl(pcie->base + PCIE_SYS_CFG_V2);
+- val |= PCIE_CSR_LTSSM_EN(port->slot) |
+- PCIE_CSR_ASPM_L1_EN(port->slot);
+- writel(val, pcie->base + PCIE_SYS_CFG_V2);
++ /* MT7622/MT7629 platforms need to enable LTSSM and ASPM. */
++ if (pcie->cfg) {
++ val = PCIE_CSR_LTSSM_EN(port->slot) |
++ PCIE_CSR_ASPM_L1_EN(port->slot);
++ regmap_update_bits(pcie->cfg, PCIE_SYS_CFG_V2, val, val);
+ }
+
+ /* Assert all reset signals */
+@@ -983,6 +986,7 @@ static int mtk_pcie_subsys_powerup(struc
+ struct device *dev = pcie->dev;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *regs;
++ struct device_node *cfg_node;
+ int err;
+
+ /* get shared registers, which are optional */
+@@ -995,6 +999,13 @@ static int mtk_pcie_subsys_powerup(struc
+ }
+ }
+
++ cfg_node = of_parse_phandle(dev->of_node, "mediatek,pcie-cfg", 0);
++ if (cfg_node) {
++ pcie->cfg = syscon_node_to_regmap(cfg_node);
++ if (IS_ERR(pcie->cfg))
++ return PTR_ERR(pcie->cfg);
++ }
++
+ pcie->free_ck = devm_clk_get(dev, "free_ck");
+ if (IS_ERR(pcie->free_ck)) {
+ if (PTR_ERR(pcie->free_ck) == -EPROBE_DEFER)
diff --git a/target/linux/mediatek/patches-5.10/602-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-MT7622.patch b/target/linux/mediatek/patches-5.10/602-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-MT7622.patch
new file mode 100644
index 0000000000..fa4a6ce2db
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/602-arm64-dts-mediatek-Split-PCIe-node-for-MT2712-MT7622.patch
@@ -0,0 +1,417 @@
+From patchwork Thu May 28 06:16:47 2020
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Chuanjia Liu <chuanjia.liu@mediatek.com>
+X-Patchwork-Id: 11574785
+Return-Path:
+ <SRS0=ftSA=7K=lists.infradead.org=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@kernel.org>
+Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org
+ [172.30.200.123])
+ by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 933301391
+ for <patchwork-linux-mediatek@patchwork.kernel.org>;
+ Thu, 28 May 2020 06:19:16 +0000 (UTC)
+Received: from bombadil.infradead.org (bombadil.infradead.org
+ [198.137.202.133])
+ (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
+ (No client certificate requested)
+ by mail.kernel.org (Postfix) with ESMTPS id D19F02078C
+ for <patchwork-linux-mediatek@patchwork.kernel.org>;
+ Thu, 28 May 2020 06:19:15 +0000 (UTC)
+Authentication-Results: mail.kernel.org;
+ dkim=pass (2048-bit key) header.d=lists.infradead.org
+ header.i=@lists.infradead.org header.b="s8K7t7DF";
+ dkim=fail reason="signature verification failed" (1024-bit key)
+ header.d=mediatek.com header.i=@mediatek.com header.b="RhX81Iqp"
+DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D19F02078C
+Authentication-Results: mail.kernel.org;
+ dmarc=fail (p=none dis=none) header.from=mediatek.com
+Authentication-Results: mail.kernel.org;
+ spf=none
+ smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
+ d=lists.infradead.org; s=bombadil.20170209; h=Sender:
+ Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:
+ List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:
+ Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description:
+ Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
+ List-Owner; bh=NHyHqNMcE7LW10MwduOJoKiWe8cv+XayY+L6WDZeSu0=; b=s8K7t7DFh1iQ5w
+ eGvuMRgXEQv/YWRuSZRyX8lx8R2H9IuawEIgkhO6lEo6xv0VdsRuj8SptfoWg5afCItMhih373M21
+ 6sUy3tEiuKGgklfxLU0reLEkaATkKRGLJDY3eSSs1mvZDrydKuZLDTka+YDGaiESlOhqMr95Nm6YM
+ yK8O00qTwSRPJUILRsBv1e/Kz8NRCmYhs56snABJkKeJ51NRAkb20R6qGTEd6UyBlz3jTVYwluLgF
+ bdqzywDT6+BNg/Agh6Zd+v2PpO4cmwCpGm62+3UUyZkfi/aQ4qZ/AFAfSQI+3ZBAgsKMC1PGifOi/
+ FgGxIvAUk6atBy7DAHuw==;
+Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org)
+ by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux))
+ id 1jeBsn-00025C-EF; Thu, 28 May 2020 06:19:13 +0000
+Received: from mailgw01.mediatek.com ([216.200.240.184])
+ by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux))
+ id 1jeBsZ-0001s4-6j; Thu, 28 May 2020 06:19:01 +0000
+X-UUID: c6210e6371fa445db0ae40a8b8a7a0a1-20200527
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
+ d=mediatek.com;
+ s=dk;
+ h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From;
+ bh=X9AwTdbhpWmlWY4LjTm8KLq4Cca3YI9UnyCX3O0BAak=;
+ b=RhX81Iqp0mWhBDyMQMFSEtt23+DGAWoin1SrFGP1bzp6GEtu38b2pK5RJVBshJtuxi/a1uMXZjeDsHJn02VGdNA07FrzZ7jq6YYEL+8cJs2DnhySmNElZazXPv2vKu9TWygfilTT24h/u8V/eszuRuhkdoUKWol8LwDlPl9gskg=;
+X-UUID: c6210e6371fa445db0ae40a8b8a7a0a1-20200527
+Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw01.mediatek.com
+ (envelope-from <chuanjia.liu@mediatek.com>)
+ (musrelay.mediatek.com ESMTP with TLS)
+ with ESMTP id 7561992; Wed, 27 May 2020 22:19:17 -0800
+Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by
+ MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id
+ 15.0.1497.2; Wed, 27 May 2020 23:18:47 -0700
+Received: from mtkcas07.mediatek.inc (172.21.101.84) by
+ mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id
+ 15.0.1497.2; Thu, 28 May 2020 14:18:52 +0800
+Received: from localhost.localdomain (10.17.3.153) by mtkcas07.mediatek.inc
+ (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend
+ Transport; Thu, 28 May 2020 14:18:51 +0800
+From: <chuanjia.liu@mediatek.com>
+To: <robh+dt@kernel.org>, <ryder.lee@mediatek.com>, <matthias.bgg@gmail.com>
+Subject: [PATCH v2 3/4] arm64: dts: mediatek: Split PCIe node for
+ MT2712/MT7622
+Date: Thu, 28 May 2020 14:16:47 +0800
+Message-ID: <20200528061648.32078-4-chuanjia.liu@mediatek.com>
+X-Mailer: git-send-email 2.18.0
+In-Reply-To: <20200528061648.32078-1-chuanjia.liu@mediatek.com>
+References: <20200528061648.32078-1-chuanjia.liu@mediatek.com>
+MIME-Version: 1.0
+X-MTK: N
+X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3
+X-CRM114-CacheID: sfid-20200527_231859_253529_B6751C5A
+X-CRM114-Status: GOOD ( 12.20 )
+X-Spam-Score: -0.2 (/)
+X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary:
+ Content analysis details: (-0.2 points)
+ pts rule name description
+ ---- ----------------------
+ --------------------------------------------------
+ -0.0 SPF_PASS SPF: sender matches SPF record
+ 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record
+ 0.0 MIME_BASE64_TEXT RAW: Message text disguised using base64
+ encoding
+ -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from
+ author's domain
+ 0.1 DKIM_SIGNED Message has a DKIM or DK signature,
+ not necessarily
+ valid
+ -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature
+ -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from
+ envelope-from domain
+ 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay
+ lines
+X-BeenThere: linux-mediatek@lists.infradead.org
+X-Mailman-Version: 2.1.29
+Precedence: list
+List-Id: <linux-mediatek.lists.infradead.org>
+List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-mediatek>,
+ <mailto:linux-mediatek-request@lists.infradead.org?subject=unsubscribe>
+List-Archive: <http://lists.infradead.org/pipermail/linux-mediatek/>
+List-Post: <mailto:linux-mediatek@lists.infradead.org>
+List-Help: <mailto:linux-mediatek-request@lists.infradead.org?subject=help>
+List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-mediatek>,
+ <mailto:linux-mediatek-request@lists.infradead.org?subject=subscribe>
+Cc: devicetree@vger.kernel.org, lorenzo.pieralisi@arm.com,
+ srv_heupstream@mediatek.com, "chuanjia.liu" <Chuanjia.Liu@mediatek.com>,
+ linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
+ jianjun.wang@mediatek.com, linux-mediatek@lists.infradead.org,
+ yong.wu@mediatek.com, bhelgaas@google.com,
+ linux-arm-kernel@lists.infradead.org, amurray@thegoodpenguin.co.uk
+Sender: "Linux-mediatek" <linux-mediatek-bounces@lists.infradead.org>
+Errors-To:
+ linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org
+
+From: "chuanjia.liu" <Chuanjia.Liu@mediatek.com>
+
+There are two independent PCIe controllers in MT2712/MT7622 platform,
+and each of them should contain an independent MSI domain.
+
+In current architecture, MSI domain will be inherited from the root
+bridge, and all of the devices will share the same MSI domain.
+Hence that, the PCIe devices will not work properly if the irq number
+which required is more than 32.
+
+Split the PCIe node for MT2712/MT7622 platform to fix MSI issue and
+comply with the hardware design.
+
+Signed-off-by: chuanjia.liu <Chuanjia.Liu@mediatek.com>
+---
+ arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 75 +++++++++++--------
+ .../dts/mediatek/mt7622-bananapi-bpi-r64.dts | 16 ++--
+ arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 6 +-
+ arch/arm64/boot/dts/mediatek/mt7622.dtsi | 68 +++++++++++------
+ 4 files changed, 96 insertions(+), 69 deletions(-)
+
+--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
+@@ -915,60 +915,73 @@
+ };
+ };
+
+- pcie: pcie@11700000 {
++ pcie1: pcie@112ff000 {
+ compatible = "mediatek,mt2712-pcie";
+ device_type = "pci";
+- reg = <0 0x11700000 0 0x1000>,
+- <0 0x112ff000 0 0x1000>;
+- reg-names = "port0", "port1";
++ reg = <0 0x112ff000 0 0x1000>;
++ reg-names = "port1";
+ #address-cells = <3>;
+ #size-cells = <2>;
+- interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+- clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
+- <&topckgen CLK_TOP_PE2_MAC_P1_SEL>,
+- <&pericfg CLK_PERI_PCIE0>,
++ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "pcie_irq";
++ clocks = <&topckgen CLK_TOP_PE2_MAC_P1_SEL>,
+ <&pericfg CLK_PERI_PCIE1>;
+- clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
+- phys = <&u3port0 PHY_TYPE_PCIE>, <&u3port1 PHY_TYPE_PCIE>;
+- phy-names = "pcie-phy0", "pcie-phy1";
++ clock-names = "sys_ck1", "ahb_ck1";
++ phys = <&u3port1 PHY_TYPE_PCIE>;
++ phy-names = "pcie-phy1";
+ bus-range = <0x00 0xff>;
+- ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>;
++ ranges = <0x82000000 0 0x11400000 0x0 0x11400000 0 0x300000>;
++ status = "disabled";
+
+- pcie0: pcie@0,0 {
+- device_type = "pci";
+- status = "disabled";
+- reg = <0x0000 0 0 0 0>;
++ slot1: pcie@1,0 {
++ reg = <0x0800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+ interrupt-map-mask = <0 0 0 7>;
+- interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+- <0 0 0 2 &pcie_intc0 1>,
+- <0 0 0 3 &pcie_intc0 2>,
+- <0 0 0 4 &pcie_intc0 3>;
+- pcie_intc0: interrupt-controller {
++ interrupt-map = <0 0 0 1 &pcie_intc1 0>,
++ <0 0 0 2 &pcie_intc1 1>,
++ <0 0 0 3 &pcie_intc1 2>,
++ <0 0 0 4 &pcie_intc1 3>;
++ pcie_intc1: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
++ };
+
+- pcie1: pcie@1,0 {
+- device_type = "pci";
+- status = "disabled";
+- reg = <0x0800 0 0 0 0>;
++ pcie0: pcie@11700000 {
++ compatible = "mediatek,mt2712-pcie";
++ device_type = "pci";
++ reg = <0 0x11700000 0 0x1000>;
++ reg-names = "port0";
++ #address-cells = <3>;
++ #size-cells = <2>;
++ interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "pcie_irq";
++ clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
++ <&pericfg CLK_PERI_PCIE0>;
++ clock-names = "sys_ck0", "ahb_ck0";
++ phys = <&u3port0 PHY_TYPE_PCIE>;
++ phy-names = "pcie-phy0";
++ bus-range = <0x00 0xff>;
++ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>;
++ status = "disabled";
++
++ slot0: pcie@0,0 {
++ reg = <0x0000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+ interrupt-map-mask = <0 0 0 7>;
+- interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+- <0 0 0 2 &pcie_intc1 1>,
+- <0 0 0 3 &pcie_intc1 2>,
+- <0 0 0 4 &pcie_intc1 3>;
+- pcie_intc1: interrupt-controller {
++ interrupt-map = <0 0 0 1 &pcie_intc0 0>,
++ <0 0 0 2 &pcie_intc0 1>,
++ <0 0 0 3 &pcie_intc0 2>,
++ <0 0 0 4 &pcie_intc0 3>;
++ pcie_intc0: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
+@@ -257,18 +257,16 @@
+ };
+ };
+
+-&pcie {
++&pcie0 {
+ pinctrl-names = "default";
+- pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>;
++ pinctrl-0 = <&pcie0_pins>;
+ status = "okay";
++};
+
+- pcie@0,0 {
+- status = "okay";
+- };
+-
+- pcie@1,0 {
+- status = "okay";
+- };
++&pcie1 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&pcie1_pins>;
++ status = "okay";
+ };
+
+ &pio {
+--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+@@ -792,45 +792,41 @@
+ #reset-cells = <1>;
+ };
+
+- pcie: pcie@1a140000 {
++ pciecfg: pciecfg@1a140000 {
++ compatible = "mediatek,mt7622-pciecfg", "syscon";
++ reg = <0 0x1a140000 0 0x1000>;
++ };
++
++ pcie0: pcie@1a143000 {
+ compatible = "mediatek,mt7622-pcie";
+ device_type = "pci";
+- reg = <0 0x1a140000 0 0x1000>,
+- <0 0x1a143000 0 0x1000>,
+- <0 0x1a145000 0 0x1000>;
+- reg-names = "subsys", "port0", "port1";
++ reg = <0 0x1a143000 0 0x1000>;
++ reg-names = "port0";
++ mediatek,pcie-cfg = <&pciecfg>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+- interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
+- <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
++ interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>;
++ interrupt-names = "pcie_irq";
+ clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
+- <&pciesys CLK_PCIE_P1_MAC_EN>,
+- <&pciesys CLK_PCIE_P0_AHB_EN>,
+ <&pciesys CLK_PCIE_P0_AHB_EN>,
+ <&pciesys CLK_PCIE_P0_AUX_EN>,
+- <&pciesys CLK_PCIE_P1_AUX_EN>,
+ <&pciesys CLK_PCIE_P0_AXI_EN>,
+- <&pciesys CLK_PCIE_P1_AXI_EN>,
+ <&pciesys CLK_PCIE_P0_OBFF_EN>,
+- <&pciesys CLK_PCIE_P1_OBFF_EN>,
+- <&pciesys CLK_PCIE_P0_PIPE_EN>,
+- <&pciesys CLK_PCIE_P1_PIPE_EN>;
+- clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
+- "aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
+- "obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
++ <&pciesys CLK_PCIE_P0_PIPE_EN>;
++ clock-names = "sys_ck0", "ahb_ck0", "aux_ck0",
++ "axi_ck0", "obff_ck0", "pipe_ck0";
++
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+ bus-range = <0x00 0xff>;
+- ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>;
++ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>;
+ status = "disabled";
+
+- pcie0: pcie@0,0 {
++ slot0: pcie@0,0 {
+ reg = <0x0000 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+- status = "disabled";
+-
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+ <0 0 0 2 &pcie_intc0 1>,
+@@ -842,15 +838,39 @@
+ #interrupt-cells = <1>;
+ };
+ };
++ };
+
+- pcie1: pcie@1,0 {
++ pcie1: pcie@1a145000 {
++ compatible = "mediatek,mt7622-pcie";
++ device_type = "pci";
++ reg = <0 0x1a145000 0 0x1000>;
++ reg-names = "port1";
++ mediatek,pcie-cfg = <&pciecfg>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
++ interrupt-names = "pcie_irq";
++ clocks = <&pciesys CLK_PCIE_P1_MAC_EN>,
++ /* designer has connect RC1 with p0_ahb clock */
++ <&pciesys CLK_PCIE_P0_AHB_EN>,
++ <&pciesys CLK_PCIE_P1_AUX_EN>,
++ <&pciesys CLK_PCIE_P1_AXI_EN>,
++ <&pciesys CLK_PCIE_P1_OBFF_EN>,
++ <&pciesys CLK_PCIE_P1_PIPE_EN>;
++ clock-names = "sys_ck1", "ahb_ck1", "aux_ck1",
++ "axi_ck1", "obff_ck1", "pipe_ck1";
++
++ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
++ bus-range = <0x00 0xff>;
++ ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>;
++ status = "disabled";
++
++ slot1: pcie@1,0 {
+ reg = <0x0800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+- status = "disabled";
+-
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+ <0 0 0 2 &pcie_intc1 1>,
+--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+@@ -232,18 +232,16 @@
+ };
+ };
+
+-&pcie {
++&pcie0 {
+ pinctrl-names = "default";
+- pinctrl-0 = <&pcie0_pins>, <&pcie1_pins>;
++ pinctrl-0 = <&pcie0_pins>;
+ status = "okay";
++};
+
+- pcie@0,0 {
+- status = "okay";
+- };
+-
+- pcie@1,0 {
+- status = "okay";
+- };
++&pcie1 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&pcie1_pins>;
++ status = "okay";
+ };
+
+ &pio {
diff --git a/target/linux/mediatek/patches-5.10/603-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch b/target/linux/mediatek/patches-5.10/603-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch
new file mode 100644
index 0000000000..799cc31ab7
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/603-ARM-dts-mediatek-Update-mt7629-PCIe-node.patch
@@ -0,0 +1,203 @@
+From patchwork Thu May 28 06:16:48 2020
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Chuanjia Liu <chuanjia.liu@mediatek.com>
+X-Patchwork-Id: 11574797
+Return-Path:
+ <SRS0=ftSA=7K=lists.infradead.org=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@kernel.org>
+Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org
+ [172.30.200.123])
+ by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 30A5E1392
+ for <patchwork-linux-mediatek@patchwork.kernel.org>;
+ Thu, 28 May 2020 06:29:05 +0000 (UTC)
+Received: from bombadil.infradead.org (bombadil.infradead.org
+ [198.137.202.133])
+ (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
+ (No client certificate requested)
+ by mail.kernel.org (Postfix) with ESMTPS id 08B6320721
+ for <patchwork-linux-mediatek@patchwork.kernel.org>;
+ Thu, 28 May 2020 06:29:05 +0000 (UTC)
+Authentication-Results: mail.kernel.org;
+ dkim=pass (2048-bit key) header.d=lists.infradead.org
+ header.i=@lists.infradead.org header.b="auhxDafY";
+ dkim=fail reason="signature verification failed" (1024-bit key)
+ header.d=mediatek.com header.i=@mediatek.com header.b="Kj09Arxb"
+DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 08B6320721
+Authentication-Results: mail.kernel.org;
+ dmarc=fail (p=none dis=none) header.from=mediatek.com
+Authentication-Results: mail.kernel.org;
+ spf=none
+ smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
+ d=lists.infradead.org; s=bombadil.20170209; h=Sender:
+ Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post:
+ List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:
+ Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description:
+ Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:
+ List-Owner; bh=+QPxF1vlOH7StIZYuXJa3V40x8QVDxCLF9AFXHblB9M=; b=auhxDafYBeaUZO
+ aYp2KVO8Aie0v4tYtRwBon7hF+x55JwD78SAxQR2RsSvrlOo9cMYYby+ToUWflVUWQ60FapAl+w+l
+ nkEjIOrLBErHwxNOcsD8T5kjyCBMqlz4OMAQYUDNJ3fSugRlGhOtxkjCGd9ebB8N2Rvu6/U8P1A9n
+ P15mEQoc+RLonR1+9mBgwTEXErjsraxkimTD4Txsp4IvMs3UdsMkP+r3OT5S/p+Uj6O9ES0h7xIon
+ aL79KaVqRLHrfZxnrVwuGiecAiTp8qLy9clHuJU32NA6ZcXH1OnWipKApgp8Ck7ys80WPKaMrat9B
+ XuskJ63w13DZAbCVvuGQ==;
+Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org)
+ by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux))
+ id 1jeC2J-00014n-M9; Thu, 28 May 2020 06:29:03 +0000
+Received: from mailgw02.mediatek.com ([216.200.240.185])
+ by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux))
+ id 1jeC2H-00013t-Li; Thu, 28 May 2020 06:29:03 +0000
+X-UUID: a4877c1586e64afeb2d6172e10605d2b-20200527
+DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
+ d=mediatek.com;
+ s=dk;
+ h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From;
+ bh=CIwcBFK1x0LbOjDt1BG6/knHFxDHRiqj8ov/jWEZDBY=;
+ b=Kj09ArxbnLVTc9bpaVPT3jQrIVjhL87sSYyVF9dFypS976k78Ce9gZd0f4K3zAZbYZHYoQtuyOQ9TOeufQfgD+Cr+j5VR7pTdO2E1iXHFs/eQAz5gAjvjlK01z1JiunrLnn9dvIr6c1gEkjQHny0VpuZ1duxx79jwYusg/Nw6Wc=;
+X-UUID: a4877c1586e64afeb2d6172e10605d2b-20200527
+Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by
+ mailgw02.mediatek.com
+ (envelope-from <chuanjia.liu@mediatek.com>)
+ (musrelay.mediatek.com ESMTP with TLS)
+ with ESMTP id 899663677; Wed, 27 May 2020 22:29:21 -0800
+Received: from MTKMBS07N2.mediatek.inc (172.21.101.141) by
+ MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id
+ 15.0.1497.2; Wed, 27 May 2020 23:18:50 -0700
+Received: from mtkcas07.mediatek.inc (172.21.101.84) by
+ mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id
+ 15.0.1497.2; Thu, 28 May 2020 14:18:54 +0800
+Received: from localhost.localdomain (10.17.3.153) by mtkcas07.mediatek.inc
+ (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend
+ Transport; Thu, 28 May 2020 14:18:52 +0800
+From: <chuanjia.liu@mediatek.com>
+To: <robh+dt@kernel.org>, <ryder.lee@mediatek.com>, <matthias.bgg@gmail.com>
+Subject: [PATCH v2 4/4] ARM: dts: mediatek: Update mt7629 PCIe node
+Date: Thu, 28 May 2020 14:16:48 +0800
+Message-ID: <20200528061648.32078-5-chuanjia.liu@mediatek.com>
+X-Mailer: git-send-email 2.18.0
+In-Reply-To: <20200528061648.32078-1-chuanjia.liu@mediatek.com>
+References: <20200528061648.32078-1-chuanjia.liu@mediatek.com>
+MIME-Version: 1.0
+X-MTK: N
+X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3
+X-CRM114-CacheID: sfid-20200527_232901_719172_E5A99C62
+X-CRM114-Status: GOOD ( 11.61 )
+X-Spam-Score: -0.2 (/)
+X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary:
+ Content analysis details: (-0.2 points)
+ pts rule name description
+ ---- ----------------------
+ --------------------------------------------------
+ -0.0 SPF_PASS SPF: sender matches SPF record
+ 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record
+ 0.0 MIME_BASE64_TEXT RAW: Message text disguised using base64
+ encoding
+ -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from
+ author's domain
+ 0.1 DKIM_SIGNED Message has a DKIM or DK signature,
+ not necessarily
+ valid
+ -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature
+ -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from
+ envelope-from domain
+ 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay
+ lines
+X-BeenThere: linux-mediatek@lists.infradead.org
+X-Mailman-Version: 2.1.29
+Precedence: list
+List-Id: <linux-mediatek.lists.infradead.org>
+List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-mediatek>,
+ <mailto:linux-mediatek-request@lists.infradead.org?subject=unsubscribe>
+List-Archive: <http://lists.infradead.org/pipermail/linux-mediatek/>
+List-Post: <mailto:linux-mediatek@lists.infradead.org>
+List-Help: <mailto:linux-mediatek-request@lists.infradead.org?subject=help>
+List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-mediatek>,
+ <mailto:linux-mediatek-request@lists.infradead.org?subject=subscribe>
+Cc: devicetree@vger.kernel.org, lorenzo.pieralisi@arm.com,
+ srv_heupstream@mediatek.com, "chuanjia.liu" <Chuanjia.Liu@mediatek.com>,
+ linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
+ jianjun.wang@mediatek.com, linux-mediatek@lists.infradead.org,
+ yong.wu@mediatek.com, bhelgaas@google.com,
+ linux-arm-kernel@lists.infradead.org, amurray@thegoodpenguin.co.uk
+Sender: "Linux-mediatek" <linux-mediatek-bounces@lists.infradead.org>
+Errors-To:
+ linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org
+
+From: "chuanjia.liu" <Chuanjia.Liu@mediatek.com>
+
+Remove unused property and add pciecfg node.
+
+Signed-off-by: chuanjia.liu <Chuanjia.Liu@mediatek.com>
+---
+ arch/arm/boot/dts/mt7629-rfb.dts | 3 ++-
+ arch/arm/boot/dts/mt7629.dtsi | 23 +++++++++++++----------
+ 2 files changed, 15 insertions(+), 11 deletions(-)
+
+--- a/arch/arm/boot/dts/mt7629-rfb.dts
++++ b/arch/arm/boot/dts/mt7629-rfb.dts
+@@ -144,9 +144,10 @@
+ };
+ };
+
+-&pcie {
++&pcie1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_pins>;
++ status = "okay";
+ };
+
+ &pciephy1 {
+--- a/arch/arm/boot/dts/mt7629.dtsi
++++ b/arch/arm/boot/dts/mt7629.dtsi
+@@ -382,16 +382,21 @@
+ #reset-cells = <1>;
+ };
+
+- pcie: pcie@1a140000 {
++ pciecfg: pciecfg@1a140000 {
++ compatible = "mediatek,mt7629-pciecfg", "syscon";
++ reg = <0x1a140000 0x1000>;
++ };
++
++ pcie1: pcie@1a145000 {
+ compatible = "mediatek,mt7629-pcie";
+ device_type = "pci";
+- reg = <0x1a140000 0x1000>,
+- <0x1a145000 0x1000>;
+- reg-names = "subsys","port1";
++ reg = <0x1a145000 0x1000>;
++ reg-names = "port1";
++ mediatek,pcie-cfg = <&pciecfg>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+- interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_LOW>,
+- <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
++ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
++ interrupt-names = "pcie_irq";
+ clocks = <&pciesys CLK_PCIE_P1_MAC_EN>,
+ <&pciesys CLK_PCIE_P0_AHB_EN>,
+ <&pciesys CLK_PCIE_P1_AUX_EN>,
+@@ -412,21 +417,19 @@
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
+ bus-range = <0x00 0xff>;
+ ranges = <0x82000000 0 0x20000000 0x20000000 0 0x10000000>;
++ status = "disabled";
+
+- pcie1: pcie@1,0 {
+- device_type = "pci";
++ slot1: pcie@1,0 {
+ reg = <0x0800 0 0 0 0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+- num-lanes = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+ <0 0 0 2 &pcie_intc1 1>,
+ <0 0 0 3 &pcie_intc1 2>,
+ <0 0 0 4 &pcie_intc1 3>;
+-
+ pcie_intc1: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
diff --git a/target/linux/mediatek/patches-5.10/610-pcie-mediatek-fix-clearing-interrupt-status.patch b/target/linux/mediatek/patches-5.10/610-pcie-mediatek-fix-clearing-interrupt-status.patch
new file mode 100644
index 0000000000..7b74a8ac73
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/610-pcie-mediatek-fix-clearing-interrupt-status.patch
@@ -0,0 +1,24 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Fri, 4 Sep 2020 18:33:27 +0200
+Subject: [PATCH] pcie-mediatek: fix clearing interrupt status
+
+Clearing the status needs to happen after running the handler, otherwise
+we will get an extra spurious interrupt after the cause has been cleared
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/pci/controller/pcie-mediatek.c
++++ b/drivers/pci/controller/pcie-mediatek.c
+@@ -613,10 +613,10 @@ static void mtk_pcie_intr_handler(struct
+ if (status & INTX_MASK) {
+ for_each_set_bit_from(bit, &status, PCI_NUM_INTX + INTX_SHIFT) {
+ /* Clear the INTx */
+- writel(1 << bit, port->base + PCIE_INT_STATUS);
+ virq = irq_find_mapping(port->irq_domain,
+ bit - INTX_SHIFT);
+ generic_handle_irq(virq);
++ writel(1 << bit, port->base + PCIE_INT_STATUS);
+ }
+ }
+
diff --git a/target/linux/mediatek/patches-5.10/700-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch b/target/linux/mediatek/patches-5.10/700-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch
new file mode 100644
index 0000000000..8c9194e5f2
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/700-net-ethernet-mtk_eth_soc-add-support-for-coherent-DM.patch
@@ -0,0 +1,85 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Fri, 4 Sep 2020 18:36:06 +0200
+Subject: [PATCH] net: ethernet: mtk_eth_soc: add support for coherent DMA
+
+It improves performance by eliminating the need for a cache flush on rx and tx
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+@@ -357,7 +357,7 @@
+ };
+
+ cci_control2: slave-if@5000 {
+- compatible = "arm,cci-400-ctrl-if";
++ compatible = "arm,cci-400-ctrl-if", "syscon";
+ interface-type = "ace";
+ reg = <0x5000 0x1000>;
+ };
+@@ -967,6 +967,8 @@
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>;
+ mediatek,ethsys = <&ethsys>;
+ mediatek,sgmiisys = <&sgmiisys>;
++ mediatek,cci-control = <&cci_control2>;
++ dma-coherent;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -9,6 +9,7 @@
+ #include <linux/of_device.h>
+ #include <linux/of_mdio.h>
+ #include <linux/of_net.h>
++#include <linux/of_address.h>
+ #include <linux/mfd/syscon.h>
+ #include <linux/regmap.h>
+ #include <linux/clk.h>
+@@ -2482,6 +2483,13 @@ static int mtk_hw_init(struct mtk_eth *e
+ if (ret)
+ goto err_disable_pm;
+
++ if (of_dma_is_coherent(eth->dev->of_node)) {
++ u32 mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA |
++ ETHSYS_DMA_AG_MAP_PPE;
++
++ regmap_update_bits(eth->ethsys, ETHSYS_DMA_AG_MAP, mask, mask);
++ }
++
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
+ ret = device_reset(eth->dev);
+ if (ret) {
+@@ -3061,6 +3069,16 @@ static int mtk_probe(struct platform_dev
+ }
+ }
+
++ if (of_dma_is_coherent(pdev->dev.of_node)) {
++ struct regmap *cci;
++
++ cci = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
++ "mediatek,cci-control");
++ /* enable CPU/bus coherency */
++ if (!IS_ERR(cci))
++ regmap_write(cci, 0, 3);
++ }
++
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
+ eth->sgmii = devm_kzalloc(eth->dev, sizeof(*eth->sgmii),
+ GFP_KERNEL);
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -437,6 +437,12 @@
+ #define RSTCTRL_FE BIT(6)
+ #define RSTCTRL_PPE BIT(31)
+
++/* ethernet dma channel agent map */
++#define ETHSYS_DMA_AG_MAP 0x408
++#define ETHSYS_DMA_AG_MAP_PDMA BIT(0)
++#define ETHSYS_DMA_AG_MAP_QDMA BIT(1)
++#define ETHSYS_DMA_AG_MAP_PPE BIT(2)
++
+ /* SGMII subsystem config registers */
+ /* Register to auto-negotiation restart */
+ #define SGMSYS_PCS_CONTROL_1 0x0
diff --git a/target/linux/mediatek/patches-5.10/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch b/target/linux/mediatek/patches-5.10/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch
new file mode 100644
index 0000000000..503cc8937d
--- /dev/null
+++ b/target/linux/mediatek/patches-5.10/710-pci-pcie-mediatek-add-support-for-coherent-DMA.patch
@@ -0,0 +1,108 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Fri, 4 Sep 2020 18:42:42 +0200
+Subject: [PATCH] pci: pcie-mediatek: add support for coherent DMA
+
+It improves performance by eliminating the need for a cache flush for DMA on
+attached devices
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+@@ -803,6 +803,8 @@
+ reg = <0 0x1a143000 0 0x1000>;
+ reg-names = "port0";
+ mediatek,pcie-cfg = <&pciecfg>;
++ mediatek,hifsys = <&hifsys>;
++ mediatek,cci-control = <&cci_control2>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>;
+@@ -820,6 +822,7 @@
+ bus-range = <0x00 0xff>;
+ ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>;
+ status = "disabled";
++ dma-coherent;
+
+ slot0: pcie@0,0 {
+ reg = <0x0000 0 0 0 0>;
+@@ -846,6 +849,8 @@
+ reg = <0 0x1a145000 0 0x1000>;
+ reg-names = "port1";
+ mediatek,pcie-cfg = <&pciecfg>;
++ mediatek,hifsys = <&hifsys>;
++ mediatek,cci-control = <&cci_control2>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
+@@ -864,6 +869,7 @@
+ bus-range = <0x00 0xff>;
+ ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>;
+ status = "disabled";
++ dma-coherent;
+
+ slot1: pcie@1,0 {
+ reg = <0x0800 0 0 0 0>;
+@@ -923,6 +929,11 @@
+ };
+ };
+
++ hifsys: syscon@1af00000 {
++ compatible = "mediatek,mt7622-hifsys", "syscon";
++ reg = <0 0x1af00000 0 0x70>;
++ };
++
+ ethsys: syscon@1b000000 {
+ compatible = "mediatek,mt7622-ethsys",
+ "syscon";
+--- a/drivers/pci/controller/pcie-mediatek.c
++++ b/drivers/pci/controller/pcie-mediatek.c
+@@ -20,6 +20,7 @@
+ #include <linux/of_address.h>
+ #include <linux/of_pci.h>
+ #include <linux/of_platform.h>
++#include <linux/of_address.h>
+ #include <linux/pci.h>
+ #include <linux/phy/phy.h>
+ #include <linux/platform_device.h>
+@@ -139,6 +140,11 @@
+ #define PCIE_LINK_STATUS_V2 0x804
+ #define PCIE_PORT_LINKUP_V2 BIT(10)
+
++/* DMA channel mapping */
++#define HIFSYS_DMA_AG_MAP 0x008
++#define HIFSYS_DMA_AG_MAP_PCIE0 BIT(0)
++#define HIFSYS_DMA_AG_MAP_PCIE1 BIT(1)
++
+ struct mtk_pcie_port;
+
+ /**
+@@ -1040,6 +1046,27 @@ static int mtk_pcie_setup(struct mtk_pci
+ struct mtk_pcie_port *port, *tmp;
+ int err;
+
++ if (of_dma_is_coherent(node)) {
++ struct regmap *con;
++ u32 mask;
++
++ con = syscon_regmap_lookup_by_phandle(node,
++ "mediatek,cci-control");
++ /* enable CPU/bus coherency */
++ if (!IS_ERR(con))
++ regmap_write(con, 0, 3);
++
++ con = syscon_regmap_lookup_by_phandle(node,
++ "mediatek,hifsys");
++ if (IS_ERR(con)) {
++ dev_err(dev, "missing hifsys node\n");
++ return PTR_ERR(con);
++ }
++
++ mask = HIFSYS_DMA_AG_MAP_PCIE0 | HIFSYS_DMA_AG_MAP_PCIE1;
++ regmap_update_bits(con, HIFSYS_DMA_AG_MAP, mask, mask);
++ }
++
+ for_each_available_child_of_node(node, child) {
+ int slot;
+