diff options
Diffstat (limited to 'target/linux/mediatek/patches-4.9')
68 files changed, 5644 insertions, 516 deletions
diff --git a/target/linux/mediatek/patches-4.9/0000-pinctrl-esw.patch b/target/linux/mediatek/patches-4.9/0000-pinctrl-esw.patch deleted file mode 100644 index 282c28d..0000000 --- a/target/linux/mediatek/patches-4.9/0000-pinctrl-esw.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/include/dt-bindings/pinctrl/mt7623-pinfunc.h -+++ b/include/dt-bindings/pinctrl/mt7623-pinfunc.h -@@ -505,6 +505,9 @@ - #define MT7623_PIN_272_G2_RXD3_FUNC_GPIO272 (MTK_PIN_NO(272) | 0) - #define MT7623_PIN_272_G2_RXD3_FUNC_G2_RXD3 (MTK_PIN_NO(272) | 1) - -+#define MT7623_PIN_273_ESW_INT_FUNC_GPIO273 (MTK_PIN_NO(273) | 0) -+#define MT7623_PIN_273_ESW_INT_FUNC_ESW_INT (MTK_PIN_NO(273) | 1) -+ - #define MT7623_PIN_274_G2_RXDV_FUNC_GPIO274 (MTK_PIN_NO(274) | 0) - #define MT7623_PIN_274_G2_RXDV_FUNC_G2_RXDV (MTK_PIN_NO(274) | 1) - ---- a/drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h -+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h -@@ -1894,8 +1894,9 @@ static const struct mtk_desc_pin mtk_pin - MTK_PIN( - PINCTRL_PIN(273, "GPIO273"), - NULL, "mt7623", -- MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), -- MTK_FUNCTION(0, "GPIO273") -+ MTK_EINT_FUNCTION(0, 168), -+ MTK_FUNCTION(0, "GPIO273"), -+ MTK_FUNCTION(1, "ESW_INT") - ), - MTK_PIN( - PINCTRL_PIN(274, "G2_RXDV"), diff --git a/target/linux/mediatek/patches-4.9/0001-NET-multi-phy-support.patch b/target/linux/mediatek/patches-4.9/0001-NET-multi-phy-support.patch deleted file mode 100644 index 0e8ce0c..0000000 --- a/target/linux/mediatek/patches-4.9/0001-NET-multi-phy-support.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 1e021917e634b173d466bf0dd3d2ae84e51a77ff Mon Sep 17 00:00:00 2001 -From: John Crispin <blogic@openwrt.org> -Date: Sun, 27 Jul 2014 09:38:50 +0100 -Subject: [PATCH 001/102] NET: multi phy support - -Signed-off-by: John Crispin <blogic@openwrt.org> ---- - drivers/net/phy/phy.c | 9 ++++++--- - include/linux/phy.h | 1 + - 2 files changed, 7 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/phy.c -+++ b/drivers/net/phy/phy.c -@@ -1035,7 +1035,8 @@ void phy_state_machine(struct work_struc - /* If the link is down, give up on negotiation for now */ - if (!phydev->link) { - phydev->state = PHY_NOLINK; -- netif_carrier_off(phydev->attached_dev); -+ if (!phydev->no_auto_carrier_off) -+ netif_carrier_off(phydev->attached_dev); - phydev->adjust_link(phydev->attached_dev); - break; - } -@@ -1127,7 +1128,8 @@ void phy_state_machine(struct work_struc - netif_carrier_on(phydev->attached_dev); - } else { - phydev->state = PHY_NOLINK; -- netif_carrier_off(phydev->attached_dev); -+ if (!phydev->no_auto_carrier_off) -+ netif_carrier_off(phydev->attached_dev); - } - - phydev->adjust_link(phydev->attached_dev); -@@ -1139,7 +1141,8 @@ void phy_state_machine(struct work_struc - case PHY_HALTED: - if (phydev->link) { - phydev->link = 0; -- netif_carrier_off(phydev->attached_dev); -+ if (!phydev->no_auto_carrier_off) -+ netif_carrier_off(phydev->attached_dev); - phydev->adjust_link(phydev->attached_dev); - do_suspend = true; - } ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -373,6 +373,7 @@ struct phy_device { - bool is_pseudo_fixed_link; - bool has_fixups; - bool suspended; -+ bool no_auto_carrier_off; - - enum phy_state state; - diff --git a/target/linux/mediatek/patches-4.9/0001-arch-arm-add-dts-build-code.patch b/target/linux/mediatek/patches-4.9/0001-arch-arm-add-dts-build-code.patch new file mode 100644 index 0000000..ff04a9f --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0001-arch-arm-add-dts-build-code.patch @@ -0,0 +1,23 @@ +From 9fdcf63545855f3a6f82dee109510f4735e861c8 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 15:54:13 +0200 +Subject: [PATCH 01/57] arch: arm: add dts build code + +Signed-off-by: John Crispin <john@phrozen.org> +--- + arch/arm/boot/dts/Makefile | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -950,6 +950,10 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ + mt6589-aquaris5.dtb \ + mt6592-evb.dtb \ + mt7623-evb.dtb \ ++ mt7623-eMMC.dtb \ ++ mt7623-NAND.dtb \ ++ mt7623-NAND-ePHY.dtb \ ++ mt7623n-bananapi-bpi-r2.dtb \ + mt8127-moose.dtb \ + mt8135-evbp1.dtb + dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb diff --git a/target/linux/mediatek/patches-4.9/0024-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch b/target/linux/mediatek/patches-4.9/0002-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch index d6fe977..9dd6fcd 100644 --- a/target/linux/mediatek/patches-4.9/0024-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch +++ b/target/linux/mediatek/patches-4.9/0002-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch @@ -1,11 +1,11 @@ -From 05be818061b9f2a0fa5ad0cde6881917ff14a2f2 Mon Sep 17 00:00:00 2001 +From ad2d4df46d8ef6a7aab20f0b668fa7db5257cbea Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Wed, 6 Jan 2016 21:55:10 +0100 -Subject: [PATCH 024/102] dt-bindings: add MediaTek PCIe binding documentation +Subject: [PATCH 02/57] dt-bindings: add MediaTek PCIe binding documentation Signed-off-by: John Crispin <blogic@openwrt.org> --- - .../devicetree/bindings/pci/mediatek-pcie.txt | 140 ++++++++++++++++++++ + .../devicetree/bindings/pci/mediatek-pcie.txt | 140 +++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/mediatek-pcie.txt diff --git a/target/linux/mediatek/patches-4.9/0025-PCI-mediatek-add-support-for-PCIe-found-on-MT7623-MT.patch b/target/linux/mediatek/patches-4.9/0003-PCI-mediatek-add-support-for-PCIe-found-on-MT7623-MT.patch index 1ab8ce2..43f51ef 100644 --- a/target/linux/mediatek/patches-4.9/0025-PCI-mediatek-add-support-for-PCIe-found-on-MT7623-MT.patch +++ b/target/linux/mediatek/patches-4.9/0003-PCI-mediatek-add-support-for-PCIe-found-on-MT7623-MT.patch @@ -1,7 +1,7 @@ -From 8ab1d4e0a9a68e03f472dee1c036a01d0198c20c Mon Sep 17 00:00:00 2001 +From 950bd9b0691dd10209c333086a6bdda0108ed3a8 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Tue, 5 Jan 2016 20:20:04 +0100 -Subject: [PATCH 025/102] PCI: mediatek: add support for PCIe found on +Subject: [PATCH 03/57] PCI: mediatek: add support for PCIe found on MT7623/MT2701 Add PCIe controller support on MediaTek MT2701/MT7623. The driver supports @@ -10,16 +10,16 @@ a single Root complex (RC) with 3 Root Ports. The SoCs supports a Gen2 Signed-off-by: John Crispin <blogic@openwrt.org> --- - arch/arm/mach-mediatek/Kconfig | 1 + - drivers/pci/host/Kconfig | 11 + - drivers/pci/host/Makefile | 1 + - drivers/pci/host/pcie-mediatek.c | 641 ++++++++++++++++++++++++++++++++++++++ + arch/arm/mach-mediatek/Kconfig | 1 + + drivers/pci/host/Kconfig | 11 + + drivers/pci/host/Makefile | 1 + + drivers/pci/host/pcie-mediatek.c | 641 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 654 insertions(+) create mode 100644 drivers/pci/host/pcie-mediatek.c --- a/arch/arm/mach-mediatek/Kconfig +++ b/arch/arm/mach-mediatek/Kconfig -@@ -29,6 +29,7 @@ config MACH_MT6592 +@@ -25,6 +25,7 @@ config MACH_MT6592 config MACH_MT7623 bool "MediaTek MT7623 SoCs support" default ARCH_MEDIATEK diff --git a/target/linux/mediatek/patches-4.9/00013-soc-mediatek-Add-MT2701-power-dt-bindings.patch b/target/linux/mediatek/patches-4.9/0004-soc-mediatek-Add-MT2701-power-dt-bindings.patch index ce38640..8d91b12 100644 --- a/target/linux/mediatek/patches-4.9/00013-soc-mediatek-Add-MT2701-power-dt-bindings.patch +++ b/target/linux/mediatek/patches-4.9/0004-soc-mediatek-Add-MT2701-power-dt-bindings.patch @@ -1,7 +1,7 @@ -From 3e96c653372d8852c45dcd3bd856975157a0fd6a Mon Sep 17 00:00:00 2001 +From 2f47c01fe3015f4c649849ddffe04f12a122abe2 Mon Sep 17 00:00:00 2001 From: Shunli Wang <shunli.wang@mediatek.com> Date: Thu, 20 Oct 2016 16:56:37 +0800 -Subject: [PATCH] soc: mediatek: Add MT2701 power dt-bindings +Subject: [PATCH 04/57] soc: mediatek: Add MT2701 power dt-bindings Add power dt-bindings for MT2701. @@ -11,9 +11,9 @@ Acked-by: Rob Herring <robh@kernel.org> Reviewed-by: Kevin Hilman <khilman@baylibre.com> Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> --- - .../devicetree/bindings/soc/mediatek/scpsys.txt | 13 +++++++---- - include/dt-bindings/power/mt2701-power.h | 27 ++++++++++++++++++++++ - 2 files changed, 35 insertions(+), 5 deletions(-) + .../devicetree/bindings/soc/mediatek/scpsys.txt | 13 ++++++----- + include/dt-bindings/power/mt2701-power.h | 26 ++++++++++++++++++++++ + 2 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 include/dt-bindings/power/mt2701-power.h --- a/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt diff --git a/target/linux/mediatek/patches-4.9/0009-clk-mediatek-Add-MT2701-clock-support.patch b/target/linux/mediatek/patches-4.9/0005-clk-mediatek-Add-MT2701-clock-support.patch index 2cd1e75..ef40ba2 100644 --- a/target/linux/mediatek/patches-4.9/0009-clk-mediatek-Add-MT2701-clock-support.patch +++ b/target/linux/mediatek/patches-4.9/0005-clk-mediatek-Add-MT2701-clock-support.patch @@ -1,7 +1,7 @@ -From a4c507d052390b42d7e8c59241e3c336796f730f Mon Sep 17 00:00:00 2001 +From f76b34c799d87ab241432b1241f6fc6d9db3ecb6 Mon Sep 17 00:00:00 2001 From: Shunli Wang <shunli.wang@mediatek.com> Date: Tue, 5 Jan 2016 14:30:20 +0800 -Subject: [PATCH 009/102] clk: mediatek: Add MT2701 clock support +Subject: [PATCH 05/57] clk: mediatek: Add MT2701 clock support Add MT2701 clock support, include topckgen, apmixedsys, infracfg, pericfg and subsystem clocks. diff --git a/target/linux/mediatek/patches-4.9/0011-reset-mediatek-mt2701-reset-driver.patch b/target/linux/mediatek/patches-4.9/0006-reset-mediatek-mt2701-reset-driver.patch index 18d4fbf..12bda9c 100644 --- a/target/linux/mediatek/patches-4.9/0011-reset-mediatek-mt2701-reset-driver.patch +++ b/target/linux/mediatek/patches-4.9/0006-reset-mediatek-mt2701-reset-driver.patch @@ -1,7 +1,7 @@ -From 3ba0020ea70ffb5503eff1823be7fa5ceda38286 Mon Sep 17 00:00:00 2001 +From 596c3a7300c0419dba71d58cbd4136e0d1e12a4e Mon Sep 17 00:00:00 2001 From: Shunli Wang <shunli.wang@mediatek.com> Date: Tue, 5 Jan 2016 14:30:22 +0800 -Subject: [PATCH 011/102] reset: mediatek: mt2701 reset driver +Subject: [PATCH 06/57] reset: mediatek: mt2701 reset driver In infrasys and perifsys, there are many reset control bits for kinds of modules. These bits are @@ -11,7 +11,7 @@ into kernel's generic reset controller framework. Signed-off-by: Shunli Wang <shunli.wang@mediatek.com> Acked-by: Philipp Zabel <p.zabel@pengutronix.de> --- - drivers/clk/mediatek/clk-mt2701.c | 4 ++++ + drivers/clk/mediatek/clk-mt2701.c | 4 ++++ 1 file changed, 4 insertions(+) --- a/drivers/clk/mediatek/clk-mt2701.c diff --git a/target/linux/mediatek/patches-4.9/0012-ARM-mediatek-Add-MT2701-config-options-for-mediatek-.patch b/target/linux/mediatek/patches-4.9/0007-ARM-mediatek-Add-MT2701-config-options-for-mediatek-.patch index 73e92dc..f38b435 100644 --- a/target/linux/mediatek/patches-4.9/0012-ARM-mediatek-Add-MT2701-config-options-for-mediatek-.patch +++ b/target/linux/mediatek/patches-4.9/0007-ARM-mediatek-Add-MT2701-config-options-for-mediatek-.patch @@ -1,8 +1,8 @@ -From 32fa899c6ab79953e4f470fb23c38bcc40edc5c8 Mon Sep 17 00:00:00 2001 +From 60c14df3cc898b6b03d66ec725f9705bf431b677 Mon Sep 17 00:00:00 2001 From: Erin Lo <erin.lo@mediatek.com> Date: Mon, 28 Dec 2015 15:09:02 +0800 -Subject: [PATCH 012/102] ARM: mediatek: Add MT2701 config options for - mediatek SoCs. +Subject: [PATCH 07/57] ARM: mediatek: Add MT2701 config options for mediatek + SoCs. The upcoming MTK pinctrl driver have a big pin table for each SoC and we don't want to bloat the kernel binary if we don't need it. @@ -11,7 +11,7 @@ Add config options so we can build for one SoC only. Add MT2701. Signed-off-by: Erin Lo <erin.lo@mediatek.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> --- - arch/arm/mach-mediatek/Kconfig | 4 ++++ + arch/arm/mach-mediatek/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) --- a/arch/arm/mach-mediatek/Kconfig diff --git a/target/linux/mediatek/patches-4.9/0014-soc-mediatek-Refine-scpsys-to-support-multiple-platf.patch b/target/linux/mediatek/patches-4.9/0008-soc-mediatek-Refine-scpsys-to-support-multiple-platf.patch index 0786e52..1d83e9a 100644 --- a/target/linux/mediatek/patches-4.9/0014-soc-mediatek-Refine-scpsys-to-support-multiple-platf.patch +++ b/target/linux/mediatek/patches-4.9/0008-soc-mediatek-Refine-scpsys-to-support-multiple-platf.patch @@ -1,7 +1,8 @@ -From 6078c651947a148c1de543b54fe55af43a63043a Mon Sep 17 00:00:00 2001 +From b5a1e520d8039c242b2157b511f684ce464d6e21 Mon Sep 17 00:00:00 2001 From: James Liao <jamesjj.liao@mediatek.com> Date: Thu, 20 Oct 2016 16:56:35 +0800 -Subject: [PATCH 1/2] soc: mediatek: Refine scpsys to support multiple platform +Subject: [PATCH 08/57] soc: mediatek: Refine scpsys to support multiple + platform Refine scpsys driver common code to support multiple SoC / platform. diff --git a/target/linux/mediatek/patches-4.9/0015-soc-mediatek-Add-MT2701-scpsys-driver.patch b/target/linux/mediatek/patches-4.9/0009-soc-mediatek-Add-MT2701-scpsys-driver.patch index 5147149..0b47635 100644 --- a/target/linux/mediatek/patches-4.9/0015-soc-mediatek-Add-MT2701-scpsys-driver.patch +++ b/target/linux/mediatek/patches-4.9/0009-soc-mediatek-Add-MT2701-scpsys-driver.patch @@ -1,7 +1,7 @@ -From 112ef1882e12094c823937f9d72f2f598db02df7 Mon Sep 17 00:00:00 2001 +From fb9f97e047f5a831a54cd61529b8cfdc4d413bb6 Mon Sep 17 00:00:00 2001 From: Shunli Wang <shunli.wang@mediatek.com> Date: Thu, 20 Oct 2016 16:56:38 +0800 -Subject: [PATCH 2/2] soc: mediatek: Add MT2701 scpsys driver +Subject: [PATCH 09/57] soc: mediatek: Add MT2701 scpsys driver Add scpsys driver for MT2701. @@ -14,8 +14,8 @@ Reviewed-by: Kevin Hilman <khilman@baylibre.com> Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> --- drivers/soc/mediatek/Kconfig | 2 +- - drivers/soc/mediatek/mtk-scpsys.c | 117 +++++++++++++++++++++++++++++++++++++- - 2 files changed, 117 insertions(+), 2 deletions(-) + drivers/soc/mediatek/mtk-scpsys.c | 108 +++++++++++++++++++++++++++++++++++++- + 2 files changed, 108 insertions(+), 2 deletions(-) --- a/drivers/soc/mediatek/Kconfig +++ b/drivers/soc/mediatek/Kconfig diff --git a/target/linux/mediatek/patches-4.9/0017-clk-add-hifsys-reset.patch b/target/linux/mediatek/patches-4.9/0010-clk-add-hifsys-reset.patch index 86d9f45..a7ebb06 100644 --- a/target/linux/mediatek/patches-4.9/0017-clk-add-hifsys-reset.patch +++ b/target/linux/mediatek/patches-4.9/0010-clk-add-hifsys-reset.patch @@ -1,7 +1,7 @@ -From f7121d2b19ddad33a09408a2c5923bfd95da8533 Mon Sep 17 00:00:00 2001 +From 600e2bd5c3019f31e90ec876f4efb6c209cf0d73 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Wed, 6 Jan 2016 20:06:49 +0100 -Subject: [PATCH 017/102] clk: add hifsys reset +Subject: [PATCH 10/57] clk: add hifsys reset Hi, @@ -14,9 +14,8 @@ thanks, Signed-off-by: John Crispin <blogic@openwrt.org> --- - drivers/clk/mediatek/clk-mt2701.c | 2 ++ - include/dt-bindings/reset-controller/mt2701-resets.h | 9 +++++++++ - 2 files changed, 11 insertions(+) + drivers/clk/mediatek/clk-mt2701.c | 2 ++ + 1 file changed, 2 insertions(+) --- a/drivers/clk/mediatek/clk-mt2701.c +++ b/drivers/clk/mediatek/clk-mt2701.c diff --git a/target/linux/mediatek/patches-4.9/0026-scpsys-various-fixes.patch b/target/linux/mediatek/patches-4.9/0011-scpsys-various-fixes.patch index 8784166..8a9da5e 100644 --- a/target/linux/mediatek/patches-4.9/0026-scpsys-various-fixes.patch +++ b/target/linux/mediatek/patches-4.9/0011-scpsys-various-fixes.patch @@ -1,13 +1,11 @@ -From 59aafd667d2880c90776931b6102b8252214d93c Mon Sep 17 00:00:00 2001 +From 1e889b3d38ab5fb425762da57313b4cc8fc2f165 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Sun, 21 Feb 2016 13:52:12 +0100 -Subject: [PATCH 026/102] scpsys: various fixes +Subject: [PATCH 11/57] scpsys: various fixes --- - drivers/clk/mediatek/clk-mt2701.c | 2 ++ - drivers/soc/mediatek/mtk-scpsys-mt2701.c | 8 -------- - include/dt-bindings/power/mt2701-power.h | 4 ++-- - 3 files changed, 4 insertions(+), 10 deletions(-) + drivers/clk/mediatek/clk-mt2701.c | 2 ++ + 1 file changed, 2 insertions(+) --- a/drivers/clk/mediatek/clk-mt2701.c +++ b/drivers/clk/mediatek/clk-mt2701.c diff --git a/target/linux/mediatek/patches-4.9/0052-clk-dont-disable-unused-clocks.patch b/target/linux/mediatek/patches-4.9/0012-clk-dont-disable-unused-clocks.patch index 7c786be..ed4111d 100644 --- a/target/linux/mediatek/patches-4.9/0052-clk-dont-disable-unused-clocks.patch +++ b/target/linux/mediatek/patches-4.9/0012-clk-dont-disable-unused-clocks.patch @@ -1,11 +1,11 @@ -From 5238c5d1d38661955ed3b52f45c46e00bfc9eb6e Mon Sep 17 00:00:00 2001 +From 0e60d2112968ccb2570535bf19fb5020c9b28c08 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 7 Apr 2016 07:18:35 +0200 -Subject: [PATCH 052/102] clk: dont disable unused clocks +Subject: [PATCH 12/57] clk: dont disable unused clocks Signed-off-by: John Crispin <blogic@openwrt.org> --- - drivers/clk/clk.c | 2 +- + drivers/clk/clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/drivers/clk/clk.c diff --git a/target/linux/mediatek/patches-4.9/0053-clk-mediatek-enable-critical-clocks.patch b/target/linux/mediatek/patches-4.9/0013-clk-mediatek-enable-critical-clocks.patch index 3993900..26257bd 100644 --- a/target/linux/mediatek/patches-4.9/0053-clk-mediatek-enable-critical-clocks.patch +++ b/target/linux/mediatek/patches-4.9/0013-clk-mediatek-enable-critical-clocks.patch @@ -1,11 +1,11 @@ -From c8fd103d6c07af5db47f061b70759b7c69169656 Mon Sep 17 00:00:00 2001 +From 03bead9276653dc842f6970250bc7eba41faf777 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 31 Mar 2016 06:46:51 +0200 -Subject: [PATCH 053/102] clk: mediatek: enable critical clocks +Subject: [PATCH 13/57] clk: mediatek: enable critical clocks Signed-off-by: John Crispin <blogic@openwrt.org> --- - drivers/clk/mediatek/clk-mt2701.c | 22 ++++++++++++++++++++-- + drivers/clk/mediatek/clk-mt2701.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) --- a/drivers/clk/mediatek/clk-mt2701.c diff --git a/target/linux/mediatek/patches-4.9/0054-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch b/target/linux/mediatek/patches-4.9/0014-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch index a22cb99..7e19c6f 100644 --- a/target/linux/mediatek/patches-4.9/0054-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch +++ b/target/linux/mediatek/patches-4.9/0014-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch @@ -1,21 +1,21 @@ -From 1387d4f0ebf4b48c09f2ea0d27a02936c3fa0010 Mon Sep 17 00:00:00 2001 +From 3a947321d72af191ee87a390295c661c876cc6f4 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Thu, 31 Mar 2016 02:26:37 +0200 -Subject: [PATCH 054/102] clk: mediatek: Export CPU mux clocks for CPU - frequency control +Subject: [PATCH 14/57] clk: mediatek: Export CPU mux clocks for CPU frequency + control This patch adds CPU mux clocks which are used by Mediatek cpufreq driver for intermediate clock source switching. Signed-off-by: Pi-Cheng Chen <pi-cheng.chen@linaro.org> --- - drivers/clk/mediatek/Makefile | 2 +- - drivers/clk/mediatek/clk-cpumux.c | 127 ++++++++++++++++++++++++++++++++ - drivers/clk/mediatek/clk-cpumux.h | 22 ++++++ - drivers/clk/mediatek/clk-mt2701.c | 8 ++ - drivers/clk/mediatek/clk-mt8173.c | 23 ++++++ - include/dt-bindings/clock/mt2701-clk.h | 3 +- - include/dt-bindings/clock/mt8173-clk.h | 4 +- + drivers/clk/mediatek/Makefile | 2 +- + drivers/clk/mediatek/clk-cpumux.c | 127 +++++++++++++++++++++++++++++++++ + drivers/clk/mediatek/clk-cpumux.h | 22 ++++++ + drivers/clk/mediatek/clk-mt2701.c | 8 +++ + drivers/clk/mediatek/clk-mt8173.c | 23 ++++++ + include/dt-bindings/clock/mt2701-clk.h | 3 +- + include/dt-bindings/clock/mt8173-clk.h | 4 +- 7 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 drivers/clk/mediatek/clk-cpumux.c create mode 100644 drivers/clk/mediatek/clk-cpumux.h diff --git a/target/linux/mediatek/patches-4.9/0055-cpufreq-mediatek-add-driver.patch b/target/linux/mediatek/patches-4.9/0015-cpufreq-mediatek-add-driver.patch index 4e7c059..af60025 100644 --- a/target/linux/mediatek/patches-4.9/0055-cpufreq-mediatek-add-driver.patch +++ b/target/linux/mediatek/patches-4.9/0015-cpufreq-mediatek-add-driver.patch @@ -1,13 +1,13 @@ -From 60f4e41b367bdb29530468c91c1e613b17a37755 Mon Sep 17 00:00:00 2001 +From 8aa2c6c4d8b20c0e9c69b15db4a0039d33f8b365 Mon Sep 17 00:00:00 2001 From: John Crispin <blogic@openwrt.org> Date: Wed, 30 Mar 2016 23:48:53 +0200 -Subject: [PATCH 055/102] cpufreq: mediatek: add driver +Subject: [PATCH 15/57] cpufreq: mediatek: add driver Signed-off-by: John Crispin <john@phrozen.org> --- - drivers/cpufreq/Kconfig.arm | 9 + - drivers/cpufreq/Makefile | 1 + - drivers/cpufreq/mt7623-cpufreq.c | 389 ++++++++++++++++++++++++++++++++++++++ + drivers/cpufreq/Kconfig.arm | 9 + + drivers/cpufreq/Makefile | 1 + + drivers/cpufreq/mt7623-cpufreq.c | 389 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 399 insertions(+) create mode 100644 drivers/cpufreq/mt7623-cpufreq.c diff --git a/target/linux/mediatek/patches-4.9/0071-pwm-add-pwm-mediatek.patch b/target/linux/mediatek/patches-4.9/0016-pwm-add-pwm-mediatek.patch index 19be772..2e8414e 100644 --- a/target/linux/mediatek/patches-4.9/0071-pwm-add-pwm-mediatek.patch +++ b/target/linux/mediatek/patches-4.9/0016-pwm-add-pwm-mediatek.patch @@ -1,16 +1,14 @@ -From 6f5941c93bdf7649f392f1263b9068d360ceab4d Mon Sep 17 00:00:00 2001 +From 201be68268eddb1568c41780a62868cc1666a2de Mon Sep 17 00:00:00 2001 From: John Crispin <john@phrozen.org> Date: Fri, 6 May 2016 02:55:48 +0200 -Subject: [PATCH 071/102] pwm: add pwm-mediatek +Subject: [PATCH 16/57] pwm: add pwm-mediatek Signed-off-by: John Crispin <john@phrozen.org> --- - arch/arm/boot/dts/mt7623-evb.dts | 17 +++ - arch/arm/boot/dts/mt7623.dtsi | 22 ++++ - drivers/pwm/Kconfig | 9 ++ - drivers/pwm/Makefile | 1 + - drivers/pwm/pwm-mediatek.c | 230 ++++++++++++++++++++++++++++++++++++++ - 5 files changed, 279 insertions(+) + drivers/pwm/Kconfig | 9 ++ + drivers/pwm/Makefile | 1 + + drivers/pwm/pwm-mediatek.c | 230 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 240 insertions(+) create mode 100644 drivers/pwm/pwm-mediatek.c --- a/drivers/pwm/Kconfig diff --git a/target/linux/mediatek/patches-4.9/0017-mfd-mt6397-Add-MT6323-LED-support-into-MT6397-driver.patch b/target/linux/mediatek/patches-4.9/0017-mfd-mt6397-Add-MT6323-LED-support-into-MT6397-driver.patch new file mode 100644 index 0000000..73ac0ee --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0017-mfd-mt6397-Add-MT6323-LED-support-into-MT6397-driver.patch @@ -0,0 +1,27 @@ +From 2b866d69f6198701457d29c5886c0ad7865c785f Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Sat, 25 Feb 2017 02:47:21 +0800 +Subject: [PATCH 17/57] mfd: mt6397: Add MT6323 LED support into MT6397 driver + +Add compatible string as "mt6323-led" that will make +the OF core spawn child devices for the LED subnode +of that MT6323 MFD device. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +--- + drivers/mfd/mt6397-core.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/mfd/mt6397-core.c ++++ b/drivers/mfd/mt6397-core.c +@@ -48,6 +48,10 @@ static const struct mfd_cell mt6323_devs + .name = "mt6323-regulator", + .of_compatible = "mediatek,mt6323-regulator" + }, ++ { ++ .name = "mt6323-led", ++ .of_compatible = "mediatek,mt6323-led" ++ }, + }; + + static const struct mfd_cell mt6397_devs[] = { diff --git a/target/linux/mediatek/patches-4.9/0085-pmic-led0.patch b/target/linux/mediatek/patches-4.9/0018-dt-bindings-leds-Add-document-bindings-for-leds-mt63.patch index dee31cd..ca0ee04 100644 --- a/target/linux/mediatek/patches-4.9/0085-pmic-led0.patch +++ b/target/linux/mediatek/patches-4.9/0018-dt-bindings-leds-Add-document-bindings-for-leds-mt63.patch @@ -1,21 +1,8 @@ -From patchwork Mon Mar 20 06:47:24 2017 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v6,1/4] dt-bindings: leds: Add document bindings for leds-mt6323 -From: sean.wang@mediatek.com -X-Patchwork-Id: 9633073 -Message-Id: <1489992447-13007-2-git-send-email-sean.wang@mediatek.com> -To: <rpurdie@rpsys.net>, <jacek.anaszewski@gmail.com>, <lee.jones@linaro.org>, - <matthias.bgg@gmail.com>, <pavel@ucw.cz>, <robh+dt@kernel.org>, - <mark.rutland@arm.com> -Cc: devicetree@vger.kernel.org, keyhaede@gmail.com, - Sean Wang <sean.wang@mediatek.com>, linux-kernel@vger.kernel.org, - linux-mediatek@lists.infradead.org, linux-leds@vger.kernel.org, - linux-arm-kernel@lists.infradead.org -Date: Mon, 20 Mar 2017 14:47:24 +0800 - +From 424ca23e68b043ce26d6981839ca825ef8637aba Mon Sep 17 00:00:00 2001 From: Sean Wang <sean.wang@mediatek.com> +Date: Mon, 20 Mar 2017 14:47:24 +0800 +Subject: [PATCH 18/57] dt-bindings: leds: Add document bindings for + leds-mt6323 This patch adds documentation for devicetree bindings for LED support on MT6323 PMIC. diff --git a/target/linux/mediatek/patches-4.9/0019-dt-bindings-mfd-Add-the-description-for-LED-as-the-s.patch b/target/linux/mediatek/patches-4.9/0019-dt-bindings-mfd-Add-the-description-for-LED-as-the-s.patch new file mode 100644 index 0000000..c8afdc0 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0019-dt-bindings-mfd-Add-the-description-for-LED-as-the-s.patch @@ -0,0 +1,24 @@ +From 7c137e4b83f32a67ccf6b39fa455aca71980a21f Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Mon, 20 Mar 2017 14:47:25 +0800 +Subject: [PATCH 19/57] dt-bindings: mfd: Add the description for LED as the + sub module + +This patch adds description for LED as the sub-module on MT6397/MT6323 +multifunction device. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +--- + Documentation/devicetree/bindings/mfd/mt6397.txt | 1 + + 1 file changed, 1 insertion(+) + +--- a/Documentation/devicetree/bindings/mfd/mt6397.txt ++++ b/Documentation/devicetree/bindings/mfd/mt6397.txt +@@ -6,6 +6,7 @@ MT6397/MT6323 is a multifunction device + - Audio codec + - GPIO + - Clock ++- LED + + It is interfaced to host controller using SPI interface by a proprietary hardware + called PMIC wrapper or pwrap. MT6397/MT6323 MFD is a child device of pwrap. diff --git a/target/linux/mediatek/patches-4.9/0087-pmic-led2.patch b/target/linux/mediatek/patches-4.9/0020-leds-Add-LED-support-for-MT6323-PMIC.patch index f0d706c..37b926d 100644 --- a/target/linux/mediatek/patches-4.9/0087-pmic-led2.patch +++ b/target/linux/mediatek/patches-4.9/0020-leds-Add-LED-support-for-MT6323-PMIC.patch @@ -1,21 +1,7 @@ -From patchwork Mon Mar 20 06:47:26 2017 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v6,3/4] leds: Add LED support for MT6323 PMIC -From: sean.wang@mediatek.com -X-Patchwork-Id: 9633081 -Message-Id: <1489992447-13007-4-git-send-email-sean.wang@mediatek.com> -To: <rpurdie@rpsys.net>, <jacek.anaszewski@gmail.com>, <lee.jones@linaro.org>, - <matthias.bgg@gmail.com>, <pavel@ucw.cz>, <robh+dt@kernel.org>, - <mark.rutland@arm.com> -Cc: devicetree@vger.kernel.org, keyhaede@gmail.com, - Sean Wang <sean.wang@mediatek.com>, linux-kernel@vger.kernel.org, - linux-mediatek@lists.infradead.org, linux-leds@vger.kernel.org, - linux-arm-kernel@lists.infradead.org -Date: Mon, 20 Mar 2017 14:47:26 +0800 - +From e482f9590f2e831c68bcf85e3f9f4c88bbd3329f Mon Sep 17 00:00:00 2001 From: Sean Wang <sean.wang@mediatek.com> +Date: Mon, 20 Mar 2017 14:47:26 +0800 +Subject: [PATCH 20/57] leds: Add LED support for MT6323 PMIC MT6323 PMIC is a multi-function device that includes LED function. It allows attaching up to 4 LEDs which can either be on, off or dimmed @@ -25,9 +11,8 @@ Signed-off-by: Sean Wang <sean.wang@mediatek.com> Reviewed-by: Jacek Anaszewski <jacek.anaszewski@gmail.com> --- drivers/leds/Kconfig | 8 + - drivers/leds/Makefile | 1 + drivers/leds/leds-mt6323.c | 502 +++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 511 insertions(+) + 2 files changed, 510 insertions(+) create mode 100644 drivers/leds/leds-mt6323.c --- a/drivers/leds/Kconfig diff --git a/target/linux/mediatek/patches-4.9/0021-mfd-mt6397-Align-the-placement-at-which-the-mfd_cell.patch b/target/linux/mediatek/patches-4.9/0021-mfd-mt6397-Align-the-placement-at-which-the-mfd_cell.patch new file mode 100644 index 0000000..79e11e8 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0021-mfd-mt6397-Align-the-placement-at-which-the-mfd_cell.patch @@ -0,0 +1,27 @@ +From 6e81b4fee93c004078465589128ba07b6855be02 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Mon, 20 Mar 2017 14:47:27 +0800 +Subject: [PATCH 21/57] mfd: mt6397: Align the placement at which the mfd_cell + of LED is defined + +Align the placement as which the mfd_cell of LED is defined as the other +members done on the structure. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Acked-by: Lee Jones <lee.jones@linaro.org> +--- + drivers/mfd/mt6397-core.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/mfd/mt6397-core.c ++++ b/drivers/mfd/mt6397-core.c +@@ -47,8 +47,7 @@ static const struct mfd_cell mt6323_devs + { + .name = "mt6323-regulator", + .of_compatible = "mediatek,mt6323-regulator" +- }, +- { ++ }, { + .name = "mt6323-led", + .of_compatible = "mediatek,mt6323-led" + }, diff --git a/target/linux/mediatek/patches-4.9/0103-nand_fixes.patch b/target/linux/mediatek/patches-4.9/0022-nand-make-bootrom-work-with-upstream-driver.patch index 874661d..f01c841 100644 --- a/target/linux/mediatek/patches-4.9/0103-nand_fixes.patch +++ b/target/linux/mediatek/patches-4.9/0022-nand-make-bootrom-work-with-upstream-driver.patch @@ -1,3 +1,13 @@ +From 453ebd5d6b535388972fcea747025ced3afca5cc Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 14:47:06 +0200 +Subject: [PATCH 22/57] nand: make bootrom work with upstream driver + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/mtd/nand/mtk_nand.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + --- a/drivers/mtd/nand/mtk_nand.c +++ b/drivers/mtd/nand/mtk_nand.c @@ -1073,8 +1073,8 @@ static int mtk_nfc_ooblayout_free(struct diff --git a/target/linux/mediatek/patches-4.9/0023-rng-add-mediatek-hw-rng.patch b/target/linux/mediatek/patches-4.9/0023-rng-add-mediatek-hw-rng.patch new file mode 100644 index 0000000..153031b --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0023-rng-add-mediatek-hw-rng.patch @@ -0,0 +1,81 @@ +From 4ad0accdfb0941de1440906461c08bee715378d5 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 15:57:44 +0200 +Subject: [PATCH 23/57] rng: add mediatek hw rng + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/char/hw_random/Kconfig | 14 ++++++++++++++ + drivers/char/hw_random/Makefile | 1 + + drivers/crypto/Kconfig | 18 ++++++++++++++++++ + drivers/crypto/Makefile | 1 + + 4 files changed, 34 insertions(+) + +--- a/drivers/char/hw_random/Kconfig ++++ b/drivers/char/hw_random/Kconfig +@@ -166,6 +166,20 @@ config HW_RANDOM_IXP4XX + + If unsure, say Y. + ++config HW_RANDOM_MTK ++ tristate "Mediatek Random Number Generator support" ++ depends on HW_RANDOM ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ default y ++ ---help--- ++ This driver provides kernel-side support for the Random Number ++ Generator hardware found on Mediatek SoCs. ++ ++ To compile this driver as a module, choose M here. the ++ module will be called mtk-rng. ++ ++ If unsure, say Y. ++ + config HW_RANDOM_OMAP + tristate "OMAP Random Number Generator support" + depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS +--- a/drivers/char/hw_random/Makefile ++++ b/drivers/char/hw_random/Makefile +@@ -35,4 +35,5 @@ obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-r + obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o + obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o + obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o ++obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o + obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -553,6 +553,24 @@ config CRYPTO_DEV_ROCKCHIP + This driver interfaces with the hardware crypto accelerator. + Supporting cbc/ecb chainmode, and aes/des/des3_ede cipher mode. + ++config CRYPTO_DEV_MEDIATEK ++ tristate "MediaTek's EIP97 Cryptographic Engine driver" ++ depends on HAS_DMA ++ depends on (ARM && ARCH_MEDIATEK) || COMPILE_TEST ++ select CRYPTO_AES ++ select CRYPTO_AEAD ++ select CRYPTO_BLKCIPHER ++ select CRYPTO_CTR ++ select CRYPTO_SHA1 ++ select CRYPTO_SHA256 ++ select CRYPTO_SHA512 ++ select CRYPTO_HMAC ++ help ++ This driver allows you to utilize the hardware crypto accelerator ++ EIP97 which can be found on the MT7623 MT2701, MT8521p, etc .... ++ Select this if you want to use it for AES/SHA1/SHA2 algorithms. ++ ++ + source "drivers/crypto/chelsio/Kconfig" + + endif # CRYPTO_HW +--- a/drivers/crypto/Makefile ++++ b/drivers/crypto/Makefile +@@ -10,6 +10,7 @@ obj-$(CONFIG_CRYPTO_DEV_IMGTEC_HASH) += + obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o + obj-$(CONFIG_CRYPTO_DEV_MV_CESA) += mv_cesa.o + obj-$(CONFIG_CRYPTO_DEV_MARVELL_CESA) += marvell/ ++obj-$(CONFIG_CRYPTO_DEV_MEDIATEK) += mediatek/ + obj-$(CONFIG_CRYPTO_DEV_MXS_DCP) += mxs-dcp.o + obj-$(CONFIG_CRYPTO_DEV_NIAGARA2) += n2_crypto.o + n2_crypto-y := n2_core.o n2_asm.o diff --git a/target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch b/target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch new file mode 100644 index 0000000..fbdfbe9 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch @@ -0,0 +1,1034 @@ +From 6e0336d1660725c06b6ab4f5361873538dbaa9f9 Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Fri, 13 Jan 2017 15:35:39 +0800 +Subject: [PATCH 24/57] media: rc: add driver for IR remote receiver on MT7623 + SoC + +This patch adds driver for IR controller on MT7623 SoC. +and should also work on similar Mediatek SoC. Currently +testing successfully on NEC and SONY remote controller +only but it should work on others (lirc, rc-5 and rc-6). + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Reviewed-by: Sean Young <sean@mess.org> +--- + drivers/media/rc/Kconfig | 11 ++ + drivers/media/rc/mtk-cir.c | 329 +++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 340 insertions(+) + create mode 100644 drivers/media/rc/mtk-cir.c + +--- a/drivers/media/rc/Kconfig ++++ b/drivers/media/rc/Kconfig +@@ -235,6 +235,17 @@ config IR_MESON + To compile this driver as a module, choose M here: the + module will be called meson-ir. + ++config IR_MTK ++ tristate "Mediatek IR remote receiver" ++ depends on RC_CORE ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ ---help--- ++ Say Y if you want to use the IR remote receiver available ++ on Mediatek SoCs. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called mtk-cir. ++ + config IR_NUVOTON + tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" + depends on PNP +--- /dev/null ++++ b/drivers/media/rc/mtk-cir.c +@@ -0,0 +1,329 @@ ++/* ++ * Driver for Mediatek IR Receiver Controller ++ * ++ * Copyright (C) 2017 Sean Wang <sean.wang@mediatek.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * 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/clk.h> ++#include <linux/interrupt.h> ++#include <linux/module.h> ++#include <linux/of_platform.h> ++#include <linux/reset.h> ++#include <media/rc-core.h> ++ ++#define MTK_IR_DEV KBUILD_MODNAME ++ ++/* Register to enable PWM and IR */ ++#define MTK_CONFIG_HIGH_REG 0x0c ++/* Enable IR pulse width detection */ ++#define MTK_PWM_EN BIT(13) ++/* Enable IR hardware function */ ++#define MTK_IR_EN BIT(0) ++ ++/* Register to setting sample period */ ++#define MTK_CONFIG_LOW_REG 0x10 ++/* Field to set sample period */ ++#define CHK_PERIOD DIV_ROUND_CLOSEST(MTK_IR_SAMPLE, \ ++ MTK_IR_CLK_PERIOD) ++#define MTK_CHK_PERIOD (((CHK_PERIOD) << 8) & (GENMASK(20, 8))) ++#define MTK_CHK_PERIOD_MASK (GENMASK(20, 8)) ++ ++/* Register to clear state of state machine */ ++#define MTK_IRCLR_REG 0x20 ++/* Bit to restart IR receiving */ ++#define MTK_IRCLR BIT(0) ++ ++/* Register containing pulse width data */ ++#define MTK_CHKDATA_REG(i) (0x88 + 4 * (i)) ++#define MTK_WIDTH_MASK (GENMASK(7, 0)) ++ ++/* Register to enable IR interrupt */ ++#define MTK_IRINT_EN_REG 0xcc ++/* Bit to enable interrupt */ ++#define MTK_IRINT_EN BIT(0) ++ ++/* Register to ack IR interrupt */ ++#define MTK_IRINT_CLR_REG 0xd0 ++/* Bit to clear interrupt status */ ++#define MTK_IRINT_CLR BIT(0) ++ ++/* Maximum count of samples */ ++#define MTK_MAX_SAMPLES 0xff ++/* Indicate the end of IR message */ ++#define MTK_IR_END(v, p) ((v) == MTK_MAX_SAMPLES && (p) == 0) ++/* Number of registers to record the pulse width */ ++#define MTK_CHKDATA_SZ 17 ++/* Source clock frequency */ ++#define MTK_IR_BASE_CLK 273000000 ++/* Frequency after IR internal divider */ ++#define MTK_IR_CLK_FREQ (MTK_IR_BASE_CLK / 4) ++/* Period for MTK_IR_CLK in ns*/ ++#define MTK_IR_CLK_PERIOD DIV_ROUND_CLOSEST(1000000000ul, \ ++ MTK_IR_CLK_FREQ) ++/* Sample period in ns */ ++#define MTK_IR_SAMPLE (MTK_IR_CLK_PERIOD * 0xc00) ++ ++/* struct mtk_ir - This is the main datasructure for holding the state ++ * of the driver ++ * @dev: The device pointer ++ * @rc: The rc instrance ++ * @irq: The IRQ that we are using ++ * @base: The mapped register i/o base ++ * @clk: The clock that we are using ++ */ ++struct mtk_ir { ++ struct device *dev; ++ struct rc_dev *rc; ++ void __iomem *base; ++ int irq; ++ struct clk *clk; ++}; ++ ++static void mtk_w32_mask(struct mtk_ir *ir, u32 val, u32 mask, unsigned int reg) ++{ ++ u32 tmp; ++ ++ tmp = __raw_readl(ir->base + reg); ++ tmp = (tmp & ~mask) | val; ++ __raw_writel(tmp, ir->base + reg); ++} ++ ++static void mtk_w32(struct mtk_ir *ir, u32 val, unsigned int reg) ++{ ++ __raw_writel(val, ir->base + reg); ++} ++ ++static u32 mtk_r32(struct mtk_ir *ir, unsigned int reg) ++{ ++ return __raw_readl(ir->base + reg); ++} ++ ++static inline void mtk_irq_disable(struct mtk_ir *ir, u32 mask) ++{ ++ u32 val; ++ ++ val = mtk_r32(ir, MTK_IRINT_EN_REG); ++ mtk_w32(ir, val & ~mask, MTK_IRINT_EN_REG); ++} ++ ++static inline void mtk_irq_enable(struct mtk_ir *ir, u32 mask) ++{ ++ u32 val; ++ ++ val = mtk_r32(ir, MTK_IRINT_EN_REG); ++ mtk_w32(ir, val | mask, MTK_IRINT_EN_REG); ++} ++ ++static irqreturn_t mtk_ir_irq(int irqno, void *dev_id) ++{ ++ struct mtk_ir *ir = dev_id; ++ u8 wid = 0; ++ u32 i, j, val; ++ DEFINE_IR_RAW_EVENT(rawir); ++ ++ /* Reset decoder state machine explicitly is required ++ * because 1) the longest duration for space MTK IR hardware ++ * could record is not safely long. e.g 12ms if rx resolution ++ * is 46us by default. There is still the risk to satisfying ++ * every decoder to reset themselves through long enough ++ * trailing spaces and 2) the IRQ handler guarantees that ++ * start of IR message is always contained in and starting ++ * from register MTK_CHKDATA_REG(0). ++ */ ++ ir_raw_event_reset(ir->rc); ++ ++ /* First message must be pulse */ ++ rawir.pulse = false; ++ ++ /* Handle all pulse and space IR controller captures */ ++ for (i = 0 ; i < MTK_CHKDATA_SZ ; i++) { ++ val = mtk_r32(ir, MTK_CHKDATA_REG(i)); ++ dev_dbg(ir->dev, "@reg%d=0x%08x\n", i, val); ++ ++ for (j = 0 ; j < 4 ; j++) { ++ wid = (val & (MTK_WIDTH_MASK << j * 8)) >> j * 8; ++ rawir.pulse = !rawir.pulse; ++ rawir.duration = wid * (MTK_IR_SAMPLE + 1); ++ ir_raw_event_store_with_filter(ir->rc, &rawir); ++ } ++ } ++ ++ /* The maximum number of edges the IR controller can ++ * hold is MTK_CHKDATA_SZ * 4. So if received IR messages ++ * is over the limit, the last incomplete IR message would ++ * be appended trailing space and still would be sent into ++ * ir-rc-raw to decode. That helps it is possible that it ++ * has enough information to decode a scancode even if the ++ * trailing end of the message is missing. ++ */ ++ if (!MTK_IR_END(wid, rawir.pulse)) { ++ rawir.pulse = false; ++ rawir.duration = MTK_MAX_SAMPLES * (MTK_IR_SAMPLE + 1); ++ ir_raw_event_store_with_filter(ir->rc, &rawir); ++ } ++ ++ ir_raw_event_handle(ir->rc); ++ ++ /* Restart controller for the next receive that would ++ * clear up all CHKDATA registers ++ */ ++ mtk_w32_mask(ir, 0x1, MTK_IRCLR, MTK_IRCLR_REG); ++ ++ /* Clear interrupt status */ ++ mtk_w32_mask(ir, 0x1, MTK_IRINT_CLR, MTK_IRINT_CLR_REG); ++ ++ return IRQ_HANDLED; ++} ++ ++static int mtk_ir_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *dn = dev->of_node; ++ struct resource *res; ++ struct mtk_ir *ir; ++ u32 val; ++ int ret = 0; ++ const char *map_name; ++ ++ ir = devm_kzalloc(dev, sizeof(struct mtk_ir), GFP_KERNEL); ++ if (!ir) ++ return -ENOMEM; ++ ++ ir->dev = dev; ++ ++ if (!of_device_is_compatible(dn, "mediatek,mt7623-cir")) ++ return -ENODEV; ++ ++ ir->clk = devm_clk_get(dev, "clk"); ++ if (IS_ERR(ir->clk)) { ++ dev_err(dev, "failed to get a ir clock.\n"); ++ return PTR_ERR(ir->clk); ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ir->base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(ir->base)) { ++ dev_err(dev, "failed to map registers\n"); ++ return PTR_ERR(ir->base); ++ } ++ ++ ir->rc = devm_rc_allocate_device(dev, RC_DRIVER_IR_RAW); ++ if (!ir->rc) { ++ dev_err(dev, "failed to allocate device\n"); ++ return -ENOMEM; ++ } ++ ++ ir->rc->priv = ir; ++ ir->rc->input_name = MTK_IR_DEV; ++ ir->rc->input_phys = MTK_IR_DEV "/input0"; ++ ir->rc->input_id.bustype = BUS_HOST; ++ ir->rc->input_id.vendor = 0x0001; ++ ir->rc->input_id.product = 0x0001; ++ ir->rc->input_id.version = 0x0001; ++ map_name = of_get_property(dn, "linux,rc-map-name", NULL); ++ ir->rc->map_name = map_name ?: RC_MAP_EMPTY; ++ ir->rc->dev.parent = dev; ++ ir->rc->driver_name = MTK_IR_DEV; ++ ir->rc->allowed_protocols = RC_BIT_ALL; ++ ir->rc->rx_resolution = MTK_IR_SAMPLE; ++ ir->rc->timeout = MTK_MAX_SAMPLES * (MTK_IR_SAMPLE + 1); ++ ++ ret = devm_rc_register_device(dev, ir->rc); ++ if (ret) { ++ dev_err(dev, "failed to register rc device\n"); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, ir); ++ ++ ir->irq = platform_get_irq(pdev, 0); ++ if (ir->irq < 0) { ++ dev_err(dev, "no irq resource\n"); ++ return -ENODEV; ++ } ++ ++ /* Enable interrupt after proper hardware ++ * setup and IRQ handler registration ++ */ ++ if (clk_prepare_enable(ir->clk)) { ++ dev_err(dev, "try to enable ir_clk failed\n"); ++ ret = -EINVAL; ++ goto exit_clkdisable_clk; ++ } ++ ++ mtk_irq_disable(ir, MTK_IRINT_EN); ++ ++ ret = devm_request_irq(dev, ir->irq, mtk_ir_irq, 0, MTK_IR_DEV, ir); ++ if (ret) { ++ dev_err(dev, "failed request irq\n"); ++ goto exit_clkdisable_clk; ++ } ++ ++ /* Enable IR and PWM */ ++ val = mtk_r32(ir, MTK_CONFIG_HIGH_REG); ++ val |= MTK_PWM_EN | MTK_IR_EN; ++ mtk_w32(ir, val, MTK_CONFIG_HIGH_REG); ++ ++ /* Setting sample period */ ++ mtk_w32_mask(ir, MTK_CHK_PERIOD, MTK_CHK_PERIOD_MASK, ++ MTK_CONFIG_LOW_REG); ++ ++ mtk_irq_enable(ir, MTK_IRINT_EN); ++ ++ dev_info(dev, "Initialized MT7623 IR driver, sample period = %luus\n", ++ DIV_ROUND_CLOSEST(MTK_IR_SAMPLE, 1000)); ++ ++ return 0; ++ ++exit_clkdisable_clk: ++ clk_disable_unprepare(ir->clk); ++ ++ return ret; ++} ++ ++static int mtk_ir_remove(struct platform_device *pdev) ++{ ++ struct mtk_ir *ir = platform_get_drvdata(pdev); ++ ++ /* Avoid contention between remove handler and ++ * IRQ handler so that disabling IR interrupt and ++ * waiting for pending IRQ handler to complete ++ */ ++ mtk_irq_disable(ir, MTK_IRINT_EN); ++ synchronize_irq(ir->irq); ++ ++ clk_disable_unprepare(ir->clk); ++ ++ return 0; ++} ++ ++static const struct of_device_id mtk_ir_match[] = { ++ { .compatible = "mediatek,mt7623-cir" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mtk_ir_match); ++ ++static struct platform_driver mtk_ir_driver = { ++ .probe = mtk_ir_probe, ++ .remove = mtk_ir_remove, ++ .driver = { ++ .name = MTK_IR_DEV, ++ .of_match_table = mtk_ir_match, ++ }, ++}; ++ ++module_platform_driver(mtk_ir_driver); ++ ++MODULE_DESCRIPTION("Mediatek IR Receiver Controller Driver"); ++MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); ++MODULE_LICENSE("GPL"); +--- a/drivers/media/rc/Makefile ++++ b/drivers/media/rc/Makefile +@@ -37,3 +37,4 @@ obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o + obj-$(CONFIG_RC_ST) += st_rc.o + obj-$(CONFIG_IR_SUNXI) += sunxi-cir.o + obj-$(CONFIG_IR_IMG) += img-ir/ ++obj-$(CONFIG_IR_MTK) += mtk-cir.o +--- a/drivers/media/rc/rc-main.c ++++ b/drivers/media/rc/rc-main.c +@@ -1355,7 +1355,7 @@ static struct device_type rc_dev_type = + .uevent = rc_dev_uevent, + }; + +-struct rc_dev *rc_allocate_device(void) ++struct rc_dev *rc_allocate_device(enum rc_driver_type type) + { + struct rc_dev *dev; + +@@ -1382,6 +1382,8 @@ struct rc_dev *rc_allocate_device(void) + dev->dev.class = &rc_class; + device_initialize(&dev->dev); + ++ dev->driver_type = type; ++ + __module_get(THIS_MODULE); + return dev; + } +@@ -1403,6 +1405,35 @@ void rc_free_device(struct rc_dev *dev) + } + EXPORT_SYMBOL_GPL(rc_free_device); + ++static void devm_rc_alloc_release(struct device *dev, void *res) ++{ ++ rc_free_device(*(struct rc_dev **)res); ++} ++ ++struct rc_dev *devm_rc_allocate_device(struct device *dev, ++ enum rc_driver_type type) ++{ ++ struct rc_dev **dr, *rc; ++ ++ dr = devres_alloc(devm_rc_alloc_release, sizeof(*dr), GFP_KERNEL); ++ if (!dr) ++ return NULL; ++ ++ rc = rc_allocate_device(type); ++ if (!rc) { ++ devres_free(dr); ++ return NULL; ++ } ++ ++ rc->dev.parent = dev; ++ rc->managed_alloc = true; ++ *dr = rc; ++ devres_add(dev, dr); ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(devm_rc_allocate_device); ++ + int rc_register_device(struct rc_dev *dev) + { + static bool raw_init = false; /* raw decoders loaded? */ +@@ -1536,6 +1567,33 @@ out_unlock: + } + EXPORT_SYMBOL_GPL(rc_register_device); + ++static void devm_rc_release(struct device *dev, void *res) ++{ ++ rc_unregister_device(*(struct rc_dev **)res); ++} ++ ++int devm_rc_register_device(struct device *parent, struct rc_dev *dev) ++{ ++ struct rc_dev **dr; ++ int ret; ++ ++ dr = devres_alloc(devm_rc_release, sizeof(*dr), GFP_KERNEL); ++ if (!dr) ++ return -ENOMEM; ++ ++ ret = rc_register_device(dev); ++ if (ret) { ++ devres_free(dr); ++ return ret; ++ } ++ ++ *dr = dev; ++ devres_add(parent, dr); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(devm_rc_register_device); ++ + void rc_unregister_device(struct rc_dev *dev) + { + if (!dev) +@@ -1557,7 +1615,8 @@ void rc_unregister_device(struct rc_dev + + ida_simple_remove(&rc_ida, dev->minor); + +- rc_free_device(dev); ++ if (!dev->managed_alloc) ++ rc_free_device(dev); + } + + EXPORT_SYMBOL_GPL(rc_unregister_device); +--- a/include/media/rc-core.h ++++ b/include/media/rc-core.h +@@ -68,6 +68,7 @@ enum rc_filter_type { + * struct rc_dev - represents a remote control device + * @dev: driver model's view of this device + * @initialized: 1 if the device init has completed, 0 otherwise ++ * @managed_alloc: devm_rc_allocate_device was used to create rc_dev + * @sysfs_groups: sysfs attribute groups + * @input_name: name of the input child device + * @input_phys: physical path to the input child device +@@ -131,6 +132,7 @@ enum rc_filter_type { + struct rc_dev { + struct device dev; + atomic_t initialized; ++ bool managed_alloc; + const struct attribute_group *sysfs_groups[5]; + const char *input_name; + const char *input_phys; +@@ -198,9 +200,19 @@ struct rc_dev { + /** + * rc_allocate_device - Allocates a RC device + * ++ * @rc_driver_type: specifies the type of the RC output to be allocated + * returns a pointer to struct rc_dev. + */ +-struct rc_dev *rc_allocate_device(void); ++struct rc_dev *rc_allocate_device(enum rc_driver_type); ++ ++/** ++ * devm_rc_allocate_device - Managed RC device allocation ++ * ++ * @dev: pointer to struct device ++ * @rc_driver_type: specifies the type of the RC output to be allocated ++ * returns a pointer to struct rc_dev. ++ */ ++struct rc_dev *devm_rc_allocate_device(struct device *dev, enum rc_driver_type); + + /** + * rc_free_device - Frees a RC device +@@ -217,6 +229,14 @@ void rc_free_device(struct rc_dev *dev); + int rc_register_device(struct rc_dev *dev); + + /** ++ * devm_rc_register_device - Manageded registering of a RC device ++ * ++ * @parent: pointer to struct device. ++ * @dev: pointer to struct rc_dev. ++ */ ++int devm_rc_register_device(struct device *parent, struct rc_dev *dev); ++ ++/** + * rc_unregister_device - Unregisters a RC device + * + * @dev: pointer to struct rc_dev. +--- a/drivers/media/common/siano/smsir.c ++++ b/drivers/media/common/siano/smsir.c +@@ -58,7 +58,7 @@ int sms_ir_init(struct smscore_device_t + struct rc_dev *dev; + + pr_debug("Allocating rc device\n"); +- dev = rc_allocate_device(); ++ dev = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!dev) + return -ENOMEM; + +--- a/drivers/media/i2c/ir-kbd-i2c.c ++++ b/drivers/media/i2c/ir-kbd-i2c.c +@@ -428,7 +428,7 @@ static int ir_probe(struct i2c_client *c + * If platform_data doesn't specify rc_dev, initialize it + * internally + */ +- rc = rc_allocate_device(); ++ rc = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!rc) + return -ENOMEM; + } +--- a/drivers/media/pci/bt8xx/bttv-input.c ++++ b/drivers/media/pci/bt8xx/bttv-input.c +@@ -424,7 +424,7 @@ int bttv_input_init(struct bttv *btv) + return -ENODEV; + + ir = kzalloc(sizeof(*ir),GFP_KERNEL); +- rc = rc_allocate_device(); ++ rc = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!ir || !rc) + goto err_out_free; + +--- a/drivers/media/pci/cx23885/cx23885-input.c ++++ b/drivers/media/pci/cx23885/cx23885-input.c +@@ -267,7 +267,6 @@ int cx23885_input_init(struct cx23885_de + struct cx23885_kernel_ir *kernel_ir; + struct rc_dev *rc; + char *rc_map; +- enum rc_driver_type driver_type; + u64 allowed_protos; + + int ret; +@@ -352,7 +351,7 @@ int cx23885_input_init(struct cx23885_de + pci_name(dev->pci)); + + /* input device */ +- rc = rc_allocate_device(); ++ rc = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!rc) { + ret = -ENOMEM; + goto err_out_free; +@@ -371,7 +370,6 @@ int cx23885_input_init(struct cx23885_de + rc->input_id.product = dev->pci->device; + } + rc->dev.parent = &dev->pci->dev; +- rc->driver_type = driver_type; + rc->allowed_protocols = allowed_protos; + rc->priv = kernel_ir; + rc->open = cx23885_input_ir_open; +--- a/drivers/media/pci/cx88/cx88-input.c ++++ b/drivers/media/pci/cx88/cx88-input.c +@@ -272,7 +272,7 @@ int cx88_ir_init(struct cx88_core *core, + */ + + ir = kzalloc(sizeof(*ir), GFP_KERNEL); +- dev = rc_allocate_device(); ++ dev = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!ir || !dev) + goto err_out_free; + +@@ -482,7 +482,6 @@ int cx88_ir_init(struct cx88_core *core, + dev->scancode_mask = hardware_mask; + + if (ir->sampling) { +- dev->driver_type = RC_DRIVER_IR_RAW; + dev->timeout = 10 * 1000 * 1000; /* 10 ms */ + } else { + dev->driver_type = RC_DRIVER_SCANCODE; +--- a/drivers/media/pci/dm1105/dm1105.c ++++ b/drivers/media/pci/dm1105/dm1105.c +@@ -744,7 +744,7 @@ static int dm1105_ir_init(struct dm1105_ + struct rc_dev *dev; + int err = -ENOMEM; + +- dev = rc_allocate_device(); ++ dev = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!dev) + return -ENOMEM; + +@@ -753,7 +753,6 @@ static int dm1105_ir_init(struct dm1105_ + + dev->driver_name = MODULE_NAME; + dev->map_name = RC_MAP_DM1105_NEC; +- dev->driver_type = RC_DRIVER_SCANCODE; + dev->input_name = "DVB on-card IR receiver"; + dev->input_phys = dm1105->ir.input_phys; + dev->input_id.bustype = BUS_PCI; +--- a/drivers/media/pci/mantis/mantis_input.c ++++ b/drivers/media/pci/mantis/mantis_input.c +@@ -39,7 +39,7 @@ int mantis_input_init(struct mantis_pci + struct rc_dev *dev; + int err; + +- dev = rc_allocate_device(); ++ dev = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!dev) { + dprintk(MANTIS_ERROR, 1, "Remote device allocation failed"); + err = -ENOMEM; +--- a/drivers/media/pci/saa7134/saa7134-input.c ++++ b/drivers/media/pci/saa7134/saa7134-input.c +@@ -849,7 +849,7 @@ int saa7134_input_init1(struct saa7134_d + } + + ir = kzalloc(sizeof(*ir), GFP_KERNEL); +- rc = rc_allocate_device(); ++ rc = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!ir || !rc) { + err = -ENOMEM; + goto err_out_free; +--- a/drivers/media/pci/smipcie/smipcie-ir.c ++++ b/drivers/media/pci/smipcie/smipcie-ir.c +@@ -183,7 +183,7 @@ int smi_ir_init(struct smi_dev *dev) + struct rc_dev *rc_dev; + struct smi_rc *ir = &dev->ir; + +- rc_dev = rc_allocate_device(); ++ rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!rc_dev) + return -ENOMEM; + +@@ -202,7 +202,6 @@ int smi_ir_init(struct smi_dev *dev) + rc_dev->input_id.product = dev->pci_dev->subsystem_device; + rc_dev->dev.parent = &dev->pci_dev->dev; + +- rc_dev->driver_type = RC_DRIVER_SCANCODE; + rc_dev->map_name = dev->info->rc_map; + + ir->rc_dev = rc_dev; +--- a/drivers/media/pci/ttpci/budget-ci.c ++++ b/drivers/media/pci/ttpci/budget-ci.c +@@ -177,7 +177,7 @@ static int msp430_ir_init(struct budget_ + struct rc_dev *dev; + int error; + +- dev = rc_allocate_device(); ++ dev = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!dev) { + printk(KERN_ERR "budget_ci: IR interface initialisation failed\n"); + return -ENOMEM; +--- a/drivers/media/rc/ati_remote.c ++++ b/drivers/media/rc/ati_remote.c +@@ -765,7 +765,6 @@ static void ati_remote_rc_init(struct at + struct rc_dev *rdev = ati_remote->rdev; + + rdev->priv = ati_remote; +- rdev->driver_type = RC_DRIVER_SCANCODE; + rdev->allowed_protocols = RC_BIT_OTHER; + rdev->driver_name = "ati_remote"; + +@@ -852,7 +851,7 @@ static int ati_remote_probe(struct usb_i + } + + ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL); +- rc_dev = rc_allocate_device(); ++ rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!ati_remote || !rc_dev) + goto exit_free_dev_rdev; + +--- a/drivers/media/rc/ene_ir.c ++++ b/drivers/media/rc/ene_ir.c +@@ -1012,7 +1012,7 @@ static int ene_probe(struct pnp_dev *pnp + + /* allocate memory */ + dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL); +- rdev = rc_allocate_device(); ++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!dev || !rdev) + goto exit_free_dev_rdev; + +--- a/drivers/media/rc/fintek-cir.c ++++ b/drivers/media/rc/fintek-cir.c +@@ -496,7 +496,7 @@ static int fintek_probe(struct pnp_dev * + return ret; + + /* input device for IR remote (and tx) */ +- rdev = rc_allocate_device(); ++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!rdev) + goto exit_free_dev_rdev; + +--- a/drivers/media/rc/gpio-ir-recv.c ++++ b/drivers/media/rc/gpio-ir-recv.c +@@ -143,14 +143,13 @@ static int gpio_ir_recv_probe(struct pla + if (!gpio_dev) + return -ENOMEM; + +- rcdev = rc_allocate_device(); ++ rcdev = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!rcdev) { + rc = -ENOMEM; + goto err_allocate_device; + } + + rcdev->priv = gpio_dev; +- rcdev->driver_type = RC_DRIVER_IR_RAW; + rcdev->input_name = GPIO_IR_DEVICE_NAME; + rcdev->input_phys = GPIO_IR_DEVICE_NAME "/input0"; + rcdev->input_id.bustype = BUS_HOST; +--- a/drivers/media/rc/igorplugusb.c ++++ b/drivers/media/rc/igorplugusb.c +@@ -190,7 +190,7 @@ static int igorplugusb_probe(struct usb_ + + usb_make_path(udev, ir->phys, sizeof(ir->phys)); + +- rc = rc_allocate_device(); ++ rc = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!rc) + goto fail; + +@@ -198,7 +198,6 @@ static int igorplugusb_probe(struct usb_ + rc->input_phys = ir->phys; + usb_to_input_id(udev, &rc->input_id); + rc->dev.parent = &intf->dev; +- rc->driver_type = RC_DRIVER_IR_RAW; + /* + * This device can only store 36 pulses + spaces, which is not enough + * for the NEC protocol and many others. +--- a/drivers/media/rc/iguanair.c ++++ b/drivers/media/rc/iguanair.c +@@ -431,7 +431,7 @@ static int iguanair_probe(struct usb_int + struct usb_host_interface *idesc; + + ir = kzalloc(sizeof(*ir), GFP_KERNEL); +- rc = rc_allocate_device(); ++ rc = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!ir || !rc) { + ret = -ENOMEM; + goto out; +--- a/drivers/media/rc/img-ir/img-ir-hw.c ++++ b/drivers/media/rc/img-ir/img-ir-hw.c +@@ -1071,7 +1071,7 @@ int img_ir_probe_hw(struct img_ir_priv * + } + + /* Allocate hardware decoder */ +- hw->rdev = rdev = rc_allocate_device(); ++ hw->rdev = rdev = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!rdev) { + dev_err(priv->dev, "cannot allocate input device\n"); + error = -ENOMEM; +--- a/drivers/media/rc/img-ir/img-ir-raw.c ++++ b/drivers/media/rc/img-ir/img-ir-raw.c +@@ -110,7 +110,7 @@ int img_ir_probe_raw(struct img_ir_priv + setup_timer(&raw->timer, img_ir_echo_timer, (unsigned long)priv); + + /* Allocate raw decoder */ +- raw->rdev = rdev = rc_allocate_device(); ++ raw->rdev = rdev = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!rdev) { + dev_err(priv->dev, "cannot allocate raw input device\n"); + return -ENOMEM; +@@ -118,7 +118,6 @@ int img_ir_probe_raw(struct img_ir_priv + rdev->priv = priv; + rdev->map_name = RC_MAP_EMPTY; + rdev->input_name = "IMG Infrared Decoder Raw"; +- rdev->driver_type = RC_DRIVER_IR_RAW; + + /* Register raw decoder */ + error = rc_register_device(rdev); +--- a/drivers/media/rc/imon.c ++++ b/drivers/media/rc/imon.c +@@ -1951,7 +1951,7 @@ static struct rc_dev *imon_init_rdev(str + const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x88 }; + +- rdev = rc_allocate_device(); ++ rdev = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!rdev) { + dev_err(ictx->dev, "remote control dev allocation failed\n"); + goto out; +@@ -1969,7 +1969,6 @@ static struct rc_dev *imon_init_rdev(str + rdev->dev.parent = ictx->dev; + + rdev->priv = ictx; +- rdev->driver_type = RC_DRIVER_SCANCODE; + rdev->allowed_protocols = RC_BIT_OTHER | RC_BIT_RC6_MCE; /* iMON PAD or MCE */ + rdev->change_protocol = imon_ir_change_protocol; + rdev->driver_name = MOD_NAME; +--- a/drivers/media/rc/ir-hix5hd2.c ++++ b/drivers/media/rc/ir-hix5hd2.c +@@ -222,7 +222,7 @@ static int hix5hd2_ir_probe(struct platf + return priv->irq; + } + +- rdev = rc_allocate_device(); ++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!rdev) + return -ENOMEM; + +--- a/drivers/media/rc/ite-cir.c ++++ b/drivers/media/rc/ite-cir.c +@@ -1472,7 +1472,7 @@ static int ite_probe(struct pnp_dev *pde + return ret; + + /* input device for IR remote (and tx) */ +- rdev = rc_allocate_device(); ++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!rdev) + goto exit_free_dev_rdev; + itdev->rdev = rdev; +--- a/drivers/media/rc/mceusb.c ++++ b/drivers/media/rc/mceusb.c +@@ -1220,7 +1220,7 @@ static struct rc_dev *mceusb_init_rc_dev + struct rc_dev *rc; + int ret; + +- rc = rc_allocate_device(); ++ rc = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!rc) { + dev_err(dev, "remote dev allocation failed"); + goto out; +--- a/drivers/media/rc/meson-ir.c ++++ b/drivers/media/rc/meson-ir.c +@@ -131,7 +131,7 @@ static int meson_ir_probe(struct platfor + return ir->irq; + } + +- ir->rc = rc_allocate_device(); ++ ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!ir->rc) { + dev_err(dev, "failed to allocate rc device\n"); + return -ENOMEM; +--- a/drivers/media/rc/rc-loopback.c ++++ b/drivers/media/rc/rc-loopback.c +@@ -181,7 +181,7 @@ static int __init loop_init(void) + struct rc_dev *rc; + int ret; + +- rc = rc_allocate_device(); ++ rc = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!rc) { + printk(KERN_ERR DRIVER_NAME ": rc_dev allocation failed\n"); + return -ENOMEM; +--- a/drivers/media/rc/st_rc.c ++++ b/drivers/media/rc/st_rc.c +@@ -235,7 +235,7 @@ static int st_rc_probe(struct platform_d + if (!rc_dev) + return -ENOMEM; + +- rdev = rc_allocate_device(); ++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW); + + if (!rdev) + return -ENOMEM; +--- a/drivers/media/rc/streamzap.c ++++ b/drivers/media/rc/streamzap.c +@@ -291,7 +291,7 @@ static struct rc_dev *streamzap_init_rc_ + struct device *dev = sz->dev; + int ret; + +- rdev = rc_allocate_device(); ++ rdev = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!rdev) { + dev_err(dev, "remote dev allocation failed\n"); + goto out; +--- a/drivers/media/rc/sunxi-cir.c ++++ b/drivers/media/rc/sunxi-cir.c +@@ -212,7 +212,7 @@ static int sunxi_ir_probe(struct platfor + goto exit_clkdisable_clk; + } + +- ir->rc = rc_allocate_device(); ++ ir->rc = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!ir->rc) { + dev_err(dev, "failed to allocate device\n"); + ret = -ENOMEM; +--- a/drivers/media/rc/ttusbir.c ++++ b/drivers/media/rc/ttusbir.c +@@ -205,7 +205,7 @@ static int ttusbir_probe(struct usb_inte + int altsetting = -1; + + tt = kzalloc(sizeof(*tt), GFP_KERNEL); +- rc = rc_allocate_device(); ++ rc = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!tt || !rc) { + ret = -ENOMEM; + goto out; +--- a/drivers/media/rc/winbond-cir.c ++++ b/drivers/media/rc/winbond-cir.c +@@ -1062,13 +1062,12 @@ wbcir_probe(struct pnp_dev *device, cons + if (err) + goto exit_free_data; + +- data->dev = rc_allocate_device(); ++ data->dev = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!data->dev) { + err = -ENOMEM; + goto exit_unregister_led; + } + +- data->dev->driver_type = RC_DRIVER_IR_RAW; + data->dev->driver_name = DRVNAME; + data->dev->input_name = WBCIR_NAME; + data->dev->input_phys = "wbcir/cir0"; +--- a/drivers/media/usb/au0828/au0828-input.c ++++ b/drivers/media/usb/au0828/au0828-input.c +@@ -298,7 +298,7 @@ int au0828_rc_register(struct au0828_dev + return -ENODEV; + + ir = kzalloc(sizeof(*ir), GFP_KERNEL); +- rc = rc_allocate_device(); ++ rc = rc_allocate_device(RC_DRIVER_IR_RAW); + if (!ir || !rc) + goto error; + +@@ -343,7 +343,6 @@ int au0828_rc_register(struct au0828_dev + rc->input_id.product = le16_to_cpu(dev->usbdev->descriptor.idProduct); + rc->dev.parent = &dev->usbdev->dev; + rc->driver_name = "au0828-input"; +- rc->driver_type = RC_DRIVER_IR_RAW; + rc->allowed_protocols = RC_BIT_NEC | RC_BIT_NECX | RC_BIT_NEC32 | + RC_BIT_RC5; + +--- a/drivers/media/usb/cx231xx/cx231xx-input.c ++++ b/drivers/media/usb/cx231xx/cx231xx-input.c +@@ -72,7 +72,7 @@ int cx231xx_ir_init(struct cx231xx *dev) + + memset(&info, 0, sizeof(struct i2c_board_info)); + memset(&dev->init_data, 0, sizeof(dev->init_data)); +- dev->init_data.rc_dev = rc_allocate_device(); ++ dev->init_data.rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!dev->init_data.rc_dev) + return -ENOMEM; + +--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c ++++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +@@ -147,7 +147,7 @@ static int dvb_usbv2_remote_init(struct + if (!d->rc.map_name) + return 0; + +- dev = rc_allocate_device(); ++ dev = rc_allocate_device(d->rc.driver_type); + if (!dev) { + ret = -ENOMEM; + goto err; +@@ -162,7 +162,6 @@ static int dvb_usbv2_remote_init(struct + /* TODO: likely RC-core should took const char * */ + dev->driver_name = (char *) d->props->driver_name; + dev->map_name = d->rc.map_name; +- dev->driver_type = d->rc.driver_type; + dev->allowed_protocols = d->rc.allowed_protos; + dev->change_protocol = d->rc.change_protocol; + dev->priv = d; +--- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c ++++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c +@@ -265,7 +265,7 @@ static int rc_core_dvb_usb_remote_init(s + int err, rc_interval; + struct rc_dev *dev; + +- dev = rc_allocate_device(); ++ dev = rc_allocate_device(d->props.rc.core.driver_type); + if (!dev) + return -ENOMEM; + +@@ -273,7 +273,6 @@ static int rc_core_dvb_usb_remote_init(s + dev->map_name = d->props.rc.core.rc_codes; + dev->change_protocol = d->props.rc.core.change_protocol; + dev->allowed_protocols = d->props.rc.core.allowed_protos; +- dev->driver_type = d->props.rc.core.driver_type; + usb_to_input_id(d->udev, &dev->input_id); + dev->input_name = "IR-receiver inside an USB DVB receiver"; + dev->input_phys = d->rc_phys; +--- a/drivers/media/usb/em28xx/em28xx-input.c ++++ b/drivers/media/usb/em28xx/em28xx-input.c +@@ -713,7 +713,7 @@ static int em28xx_ir_init(struct em28xx + ir = kzalloc(sizeof(*ir), GFP_KERNEL); + if (!ir) + return -ENOMEM; +- rc = rc_allocate_device(); ++ rc = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!rc) + goto error; + +--- a/drivers/media/usb/tm6000/tm6000-input.c ++++ b/drivers/media/usb/tm6000/tm6000-input.c +@@ -429,7 +429,7 @@ int tm6000_ir_init(struct tm6000_core *d + return 0; + + ir = kzalloc(sizeof(*ir), GFP_ATOMIC); +- rc = rc_allocate_device(); ++ rc = rc_allocate_device(RC_DRIVER_SCANCODE); + if (!ir || !rc) + goto out; + +@@ -456,7 +456,6 @@ int tm6000_ir_init(struct tm6000_core *d + ir->polling = 50; + INIT_DELAYED_WORK(&ir->work, tm6000_ir_handle_key); + } +- rc->driver_type = RC_DRIVER_SCANCODE; + + snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)", + dev->name); diff --git a/target/linux/mediatek/patches-4.9/0091-dsa1.patch b/target/linux/mediatek/patches-4.9/0025-dt-bindings-net-dsa-add-Mediatek-MT7530-binding.patch index ffc63dc..24e13d1 100644 --- a/target/linux/mediatek/patches-4.9/0091-dsa1.patch +++ b/target/linux/mediatek/patches-4.9/0025-dt-bindings-net-dsa-add-Mediatek-MT7530-binding.patch @@ -1,21 +1,7 @@ -From patchwork Wed Mar 29 09:38:19 2017 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [net-next,v3,1/5] dt-bindings: net: dsa: add Mediatek MT7530 binding -From: sean.wang@mediatek.com -X-Patchwork-Id: 9651093 -Message-Id: <1490780303-18598-2-git-send-email-sean.wang@mediatek.com> -To: <andrew@lunn.ch>, <f.fainelli@gmail.com>, - <vivien.didelot@savoirfairelinux.com>, <matthias.bgg@gmail.com>, - <robh+dt@kernel.org>, <mark.rutland@arm.com> -Cc: devicetree@vger.kernel.org, Landen.Chao@mediatek.com, keyhaede@gmail.com, - netdev@vger.kernel.org, sean.wang@mediatek.com, - linux-kernel@vger.kernel.org, - linux-mediatek@lists.infradead.org, objelf@gmail.com, davem@davemloft.net -Date: Wed, 29 Mar 2017 17:38:19 +0800 - +From 3b9b46b5705214b16c5356284ad68be32ae56a26 Mon Sep 17 00:00:00 2001 From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 29 Mar 2017 17:38:19 +0800 +Subject: [PATCH 25/57] dt-bindings: net: dsa: add Mediatek MT7530 binding Add device-tree binding for Mediatek MT7530 switch. diff --git a/target/linux/mediatek/patches-4.9/0026-net-mediatek-backport-v4.10-driver.patch b/target/linux/mediatek/patches-4.9/0026-net-mediatek-backport-v4.10-driver.patch new file mode 100644 index 0000000..8a6d593 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0026-net-mediatek-backport-v4.10-driver.patch @@ -0,0 +1,1788 @@ +From 99d9d02a05df503184be094de336e7515fe3e235 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 14:26:29 +0200 +Subject: [PATCH 26/57] net: mediatek: backport v4.10 driver + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 49 ++- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 16 +- + drivers/net/ethernet/mediatek/mtk_hnat/Makefile | 4 + + drivers/net/ethernet/mediatek/mtk_hnat/hnat.c | 315 +++++++++++++++ + drivers/net/ethernet/mediatek/mtk_hnat/hnat.h | 425 +++++++++++++++++++++ + .../net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c | 259 +++++++++++++ + .../net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c | 289 ++++++++++++++ + .../net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h | 44 +++ + 8 files changed, 1378 insertions(+), 23 deletions(-) + create mode 100644 drivers/net/ethernet/mediatek/mtk_hnat/Makefile + create mode 100644 drivers/net/ethernet/mediatek/mtk_hnat/hnat.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_hnat/hnat.h + create mode 100644 drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -462,8 +462,8 @@ static void mtk_stats_update(struct mtk_ + } + } + +-static struct rtnl_link_stats64 *mtk_get_stats64(struct net_device *dev, +- struct rtnl_link_stats64 *storage) ++static struct rtnl_link_stats64 * mtk_get_stats64(struct net_device *dev, ++ struct rtnl_link_stats64 *storage) + { + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_hw_stats *hw_stats = mac->hw_stats; +@@ -615,7 +615,7 @@ static int mtk_tx_map(struct sk_buff *sk + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; + struct mtk_tx_dma *itxd, *txd; +- struct mtk_tx_buf *tx_buf; ++ struct mtk_tx_buf *itx_buf, *tx_buf; + dma_addr_t mapped_addr; + unsigned int nr_frags; + int i, n_desc = 1; +@@ -629,8 +629,8 @@ static int mtk_tx_map(struct sk_buff *sk + fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT; + txd4 |= fport; + +- tx_buf = mtk_desc_to_tx_buf(ring, itxd); +- memset(tx_buf, 0, sizeof(*tx_buf)); ++ itx_buf = mtk_desc_to_tx_buf(ring, itxd); ++ memset(itx_buf, 0, sizeof(*itx_buf)); + + if (gso) + txd4 |= TX_DMA_TSO; +@@ -649,9 +649,11 @@ static int mtk_tx_map(struct sk_buff *sk + return -ENOMEM; + + WRITE_ONCE(itxd->txd1, mapped_addr); +- tx_buf->flags |= MTK_TX_FLAGS_SINGLE0; +- dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr); +- dma_unmap_len_set(tx_buf, dma_len0, skb_headlen(skb)); ++ itx_buf->flags |= MTK_TX_FLAGS_SINGLE0; ++ itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 : ++ MTK_TX_FLAGS_FPORT1; ++ dma_unmap_addr_set(itx_buf, dma_addr0, mapped_addr); ++ dma_unmap_len_set(itx_buf, dma_len0, skb_headlen(skb)); + + /* TX SG offload */ + txd = itxd; +@@ -687,11 +689,13 @@ static int mtk_tx_map(struct sk_buff *sk + last_frag * TX_DMA_LS0)); + WRITE_ONCE(txd->txd4, fport); + +- tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC; + tx_buf = mtk_desc_to_tx_buf(ring, txd); + memset(tx_buf, 0, sizeof(*tx_buf)); +- ++ tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC; + tx_buf->flags |= MTK_TX_FLAGS_PAGE0; ++ tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 : ++ MTK_TX_FLAGS_FPORT1; ++ + dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr); + dma_unmap_len_set(tx_buf, dma_len0, frag_map_size); + frag_size -= frag_map_size; +@@ -700,7 +704,7 @@ static int mtk_tx_map(struct sk_buff *sk + } + + /* store skb to cleanup */ +- tx_buf->skb = skb; ++ itx_buf->skb = skb; + + WRITE_ONCE(itxd->txd4, txd4); + WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) | +@@ -845,7 +849,7 @@ static int mtk_start_xmit(struct sk_buff + drop: + spin_unlock(ð->page_lock); + stats->tx_dropped++; +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +@@ -1014,17 +1018,16 @@ static int mtk_poll_tx(struct mtk_eth *e + + while ((cpu != dma) && budget) { + u32 next_cpu = desc->txd2; +- int mac; ++ int mac = 0; + + desc = mtk_qdma_phys_to_virt(ring, desc->txd2); + if ((desc->txd3 & TX_DMA_OWNER_CPU) == 0) + break; + +- mac = (desc->txd4 >> TX_DMA_FPORT_SHIFT) & +- TX_DMA_FPORT_MASK; +- mac--; +- + tx_buf = mtk_desc_to_tx_buf(ring, desc); ++ if (tx_buf->flags & MTK_TX_FLAGS_FPORT1) ++ mac = 1; ++ + skb = tx_buf->skb; + if (!skb) { + condition = 1; +@@ -1848,6 +1851,12 @@ static int mtk_hw_init(struct mtk_eth *e + /* GE2, Force 1000M/FD, FC ON */ + mtk_w32(eth, MAC_MCR_FIXED_LINK, MTK_MAC_MCR(1)); + ++ /* Indicates CDM to parse the MTK special tag from CPU ++ * which also is working out for untag packets. ++ */ ++ val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); ++ mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); ++ + /* Enable RX VLan Offloading */ + mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); + +@@ -1910,10 +1919,9 @@ static int __init mtk_init(struct net_de + + /* If the mac address is invalid, use random mac address */ + if (!is_valid_ether_addr(dev->dev_addr)) { +- random_ether_addr(dev->dev_addr); ++ eth_hw_addr_random(dev); + dev_err(eth->dev, "generated random MAC address %pM\n", + dev->dev_addr); +- dev->addr_assign_type = NET_ADDR_RANDOM; + } + + return mtk_phy_connect(dev); +@@ -2247,7 +2255,6 @@ static const struct net_device_ops mtk_n + .ndo_set_mac_address = mtk_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = mtk_do_ioctl, +- .ndo_change_mtu = eth_change_mtu, + .ndo_tx_timeout = mtk_tx_timeout, + .ndo_get_stats64 = mtk_get_stats64, + .ndo_fix_features = mtk_fix_features, +@@ -2320,6 +2327,8 @@ static int mtk_add_mac(struct mtk_eth *e + eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops; + + eth->netdev[id]->irq = eth->irq[0]; ++ eth->netdev[id]->dev.of_node = np; ++ + return 0; + + free_netdev: +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -70,6 +70,10 @@ + /* Frame Engine Interrupt Grouping Register */ + #define MTK_FE_INT_GRP 0x20 + ++/* CDMP Ingress Control Register */ ++#define MTK_CDMQ_IG_CTRL 0x1400 ++#define MTK_CDMQ_STAG_EN BIT(0) ++ + /* CDMP Exgress Control Register */ + #define MTK_CDMP_EG_CTRL 0x404 + +@@ -406,12 +410,18 @@ struct mtk_hw_stats { + struct u64_stats_sync syncp; + }; + +-/* PDMA descriptor can point at 1-2 segments. This enum allows us to track how +- * memory was allocated so that it can be freed properly +- */ + enum mtk_tx_flags { ++ /* PDMA descriptor can point at 1-2 segments. This enum allows us to ++ * track how memory was allocated so that it can be freed properly. ++ */ + MTK_TX_FLAGS_SINGLE0 = 0x01, + MTK_TX_FLAGS_PAGE0 = 0x02, ++ ++ /* MTK_TX_FLAGS_FPORTx allows tracking which port the transmitted ++ * SKB out instead of looking up through hardware TX descriptor. ++ */ ++ MTK_TX_FLAGS_FPORT0 = 0x04, ++ MTK_TX_FLAGS_FPORT1 = 0x08, + }; + + /* This enum allows us to identify how the clock is defined on the array of the +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_hnat/Makefile +@@ -0,0 +1,4 @@ ++ccflags-y=-Werror ++ ++obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtkhnat.o ++mtkhnat-objs := hnat.o hnat_nf_hook.o hnat_debugfs.o +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c +@@ -0,0 +1,315 @@ ++/* This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * 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. ++ * ++ * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com> ++ * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org> ++ */ ++ ++#include <linux/dma-mapping.h> ++#include <linux/delay.h> ++#include <linux/if.h> ++#include <linux/io.h> ++#include <linux/module.h> ++#include <linux/of_device.h> ++#include <linux/platform_device.h> ++#include <linux/reset.h> ++ ++#include "hnat.h" ++ ++struct hnat_priv *host; ++ ++static void cr_set_bits(void __iomem * reg, u32 bs) ++{ ++ u32 val = readl(reg); ++ ++ val |= bs; ++ writel(val, reg); ++} ++ ++static void cr_clr_bits(void __iomem * reg, u32 bs) ++{ ++ u32 val = readl(reg); ++ ++ val &= ~bs; ++ writel(val, reg); ++} ++ ++static void cr_set_field(void __iomem * reg, u32 field, u32 val) ++{ ++ unsigned int tv = readl(reg); ++ ++ tv &= ~field; ++ tv |= ((val) << (ffs((unsigned int)field) - 1)); ++ writel(tv, reg); ++} ++ ++static int hnat_start(void) ++{ ++ u32 foe_table_sz; ++ ++ /* mapp the FOE table */ ++ foe_table_sz = FOE_4TB_SIZ * sizeof(struct foe_entry); ++ host->foe_table_cpu = ++ dma_alloc_coherent(host->dev, foe_table_sz, &host->foe_table_dev, ++ GFP_KERNEL); ++ if (!host->foe_table_cpu) ++ return -1; ++ ++ writel(host->foe_table_dev, host->ppe_base + PPE_TB_BASE); ++ memset(host->foe_table_cpu, 0, foe_table_sz); ++ ++ /* setup hashing */ ++ cr_set_field(host->ppe_base + PPE_TB_CFG, TB_ETRY_NUM, TABLE_4K); ++ cr_set_field(host->ppe_base + PPE_TB_CFG, HASH_MODE, HASH_MODE_1); ++ writel(HASH_SEED_KEY, host->ppe_base + PPE_HASH_SEED); ++ cr_set_field(host->ppe_base + PPE_TB_CFG, XMODE, 0); ++ cr_set_field(host->ppe_base + PPE_TB_CFG, TB_ENTRY_SIZE, ENTRY_64B); ++ cr_set_field(host->ppe_base + PPE_TB_CFG, SMA, SMA_FWD_CPU_BUILD_ENTRY); ++ ++ /* set ip proto */ ++ writel(0xFFFFFFFF, host->ppe_base + PPE_IP_PROT_CHK); ++ ++ /* setup caching */ ++ cr_set_field(host->ppe_base + PPE_CAH_CTRL, CAH_X_MODE, 1); ++ cr_set_field(host->ppe_base + PPE_CAH_CTRL, CAH_X_MODE, 0); ++ cr_set_field(host->ppe_base + PPE_CAH_CTRL, CAH_EN, 1); ++ ++ /* enable FOE */ ++ cr_set_bits(host->ppe_base + PPE_FLOW_CFG, ++ BIT_IPV4_NAT_EN | BIT_IPV4_NAPT_EN | ++ BIT_IPV4_NAT_FRAG_EN | BIT_IPV4_HASH_GREK); ++ ++ /* setup FOE aging */ ++ cr_set_field(host->ppe_base + PPE_TB_CFG, NTU_AGE, 1); ++ cr_set_field(host->ppe_base + PPE_TB_CFG, UNBD_AGE, 1); ++ cr_set_field(host->ppe_base + PPE_UNB_AGE, UNB_MNP, 1000); ++ cr_set_field(host->ppe_base + PPE_UNB_AGE, UNB_DLTA, 3); ++ cr_set_field(host->ppe_base + PPE_TB_CFG, TCP_AGE, 1); ++ cr_set_field(host->ppe_base + PPE_TB_CFG, UDP_AGE, 1); ++ cr_set_field(host->ppe_base + PPE_TB_CFG, FIN_AGE, 1); ++ cr_set_field(host->ppe_base + PPE_BND_AGE_0, UDP_DLTA, 5); ++ cr_set_field(host->ppe_base + PPE_BND_AGE_0, NTU_DLTA, 5); ++ cr_set_field(host->ppe_base + PPE_BND_AGE_1, FIN_DLTA, 5); ++ cr_set_field(host->ppe_base + PPE_BND_AGE_1, TCP_DLTA, 5); ++ ++ /* setup FOE ka */ ++ cr_set_field(host->ppe_base + PPE_TB_CFG, KA_CFG, 3); ++ cr_set_field(host->ppe_base + PPE_KA, KA_T, 1); ++ cr_set_field(host->ppe_base + PPE_KA, TCP_KA, 1); ++ cr_set_field(host->ppe_base + PPE_KA, UDP_KA, 1); ++ cr_set_field(host->ppe_base + PPE_BIND_LMT_1, NTU_KA, 1); ++ ++ /* setup FOE rate limit */ ++ cr_set_field(host->ppe_base + PPE_BIND_LMT_0, QURT_LMT, 16383); ++ cr_set_field(host->ppe_base + PPE_BIND_LMT_0, HALF_LMT, 16383); ++ cr_set_field(host->ppe_base + PPE_BIND_LMT_1, FULL_LMT, 16383); ++ cr_set_field(host->ppe_base + PPE_BNDR, BIND_RATE, 1); ++ ++ /* setup FOE cf gen */ ++ cr_set_field(host->ppe_base + PPE_GLO_CFG, PPE_EN, 1); ++ writel(0, host->ppe_base + PPE_DFT_CPORT); // pdma ++ //writel(0x55555555, host->ppe_base + PPE_DFT_CPORT); //qdma ++ cr_set_field(host->ppe_base + PPE_GLO_CFG, TTL0_DRP, 1); ++ ++ /* fwd packets from gmac to PPE */ ++ cr_clr_bits(host->fe_base + GDMA1_FWD_CFG, GDM1_ALL_FRC_MASK); ++ cr_set_bits(host->fe_base + GDMA1_FWD_CFG, ++ BITS_GDM1_ALL_FRC_P_PPE); ++ cr_clr_bits(host->fe_base + GDMA2_FWD_CFG, GDM2_ALL_FRC_MASK); ++ cr_set_bits(host->fe_base + GDMA2_FWD_CFG, ++ BITS_GDM2_ALL_FRC_P_PPE); ++ ++ dev_info(host->dev, "hwnat start\n"); ++ ++ return 0; ++} ++ ++static int ppe_busy_wait(void) ++{ ++ unsigned long t_start = jiffies; ++ u32 r = 0; ++ ++ while (1) { ++ r = readl((host->ppe_base + 0x0)); ++ if (!(r & BIT(31))) ++ return 0; ++ if (time_after(jiffies, t_start + HZ)) ++ break; ++ usleep_range(10, 20); ++ } ++ ++ dev_err(host->dev, "ppe:%s timeout\n", __func__); ++ ++ return -1; ++} ++ ++static void hnat_stop(void) ++{ ++ u32 foe_table_sz; ++ struct foe_entry *entry, *end; ++ u32 r1 = 0, r2 = 0; ++ ++ /* discard all traffic while we disable the PPE */ ++ cr_clr_bits(host->fe_base + GDMA1_FWD_CFG, GDM1_ALL_FRC_MASK); ++ cr_set_bits(host->fe_base + GDMA1_FWD_CFG, ++ BITS_GDM1_ALL_FRC_P_DISCARD); ++ cr_clr_bits(host->fe_base + GDMA2_FWD_CFG, GDM2_ALL_FRC_MASK); ++ cr_set_bits(host->fe_base + GDMA2_FWD_CFG, ++ BITS_GDM2_ALL_FRC_P_DISCARD); ++ ++ if (ppe_busy_wait()) { ++ reset_control_reset(host->rstc); ++ msleep(2000); ++ return; ++ } ++ ++ entry = host->foe_table_cpu; ++ end = host->foe_table_cpu + FOE_4TB_SIZ; ++ while (entry < end) { ++ entry->bfib1.state = INVALID; ++ entry++; ++ } ++ ++ /* disable caching */ ++ cr_set_field(host->ppe_base + PPE_CAH_CTRL, CAH_X_MODE, 1); ++ cr_set_field(host->ppe_base + PPE_CAH_CTRL, CAH_X_MODE, 0); ++ cr_set_field(host->ppe_base + PPE_CAH_CTRL, CAH_EN, 0); ++ ++ /* flush cache has to be ahead of hnat diable --*/ ++ cr_set_field(host->ppe_base + PPE_GLO_CFG, PPE_EN, 0); ++ ++ /* disable FOE */ ++ cr_clr_bits(host->ppe_base + PPE_FLOW_CFG, ++ BIT_IPV4_NAPT_EN | BIT_IPV4_NAT_EN | ++ BIT_IPV4_NAT_FRAG_EN | ++ BIT_FUC_FOE | BIT_FMC_FOE | BIT_FUC_FOE); ++ ++ /* disable FOE aging */ ++ cr_set_field(host->ppe_base + PPE_TB_CFG, NTU_AGE, 0); ++ cr_set_field(host->ppe_base + PPE_TB_CFG, UNBD_AGE, 0); ++ cr_set_field(host->ppe_base + PPE_TB_CFG, TCP_AGE, 0); ++ cr_set_field(host->ppe_base + PPE_TB_CFG, UDP_AGE, 0); ++ cr_set_field(host->ppe_base + PPE_TB_CFG, FIN_AGE, 0); ++ ++ r1 = readl(host->fe_base + 0x100); ++ r2 = readl(host->fe_base + 0x10c); ++ ++ dev_info(host->dev, "0x100 = 0x%x, 0x10c = 0x%x\n", r1, r2); ++ ++ if (((r1 & 0xff00) >> 0x8) >= (r1 & 0xff) || ++ ((r1 & 0xff00) >> 0x8) >= (r2 & 0xff)) { ++ dev_info(host->dev, "reset pse\n"); ++ writel(0x1, host->fe_base + 0x4); ++ } ++ ++ /* free the FOE table */ ++ foe_table_sz = FOE_4TB_SIZ * sizeof(struct foe_entry); ++ dma_free_coherent(NULL, foe_table_sz, host->foe_table_cpu, ++ host->foe_table_dev); ++ writel(0, host->ppe_base + PPE_TB_BASE); ++ ++ if (ppe_busy_wait()) { ++ reset_control_reset(host->rstc); ++ msleep(2000); ++ return; ++ } ++ ++ /* send all traffic back to the DMA engine */ ++ cr_clr_bits(host->fe_base + GDMA1_FWD_CFG, GDM1_ALL_FRC_MASK); ++ cr_set_bits(host->fe_base + GDMA1_FWD_CFG, ++ BITS_GDM1_ALL_FRC_P_CPU_PDMA); ++ cr_clr_bits(host->fe_base + GDMA2_FWD_CFG, GDM2_ALL_FRC_MASK); ++ cr_set_bits(host->fe_base + GDMA2_FWD_CFG, ++ BITS_GDM2_ALL_FRC_P_CPU_PDMA); ++} ++ ++static int hnat_probe(struct platform_device *pdev) ++{ ++ int err = 0; ++ struct resource *res ; ++ const char *name; ++ struct device_node *np; ++ ++ host = devm_kzalloc(&pdev->dev, sizeof(struct hnat_priv), GFP_KERNEL); ++ if (!host) ++ return -ENOMEM; ++ ++ host->dev = &pdev->dev; ++ np = host->dev->of_node; ++ ++ err = of_property_read_string(np, "mtketh-wan", &name); ++ if (err < 0) ++ return -EINVAL; ++ ++ strncpy(host->wan, (char *)name, IFNAMSIZ); ++ dev_info(&pdev->dev, "wan = %s\n", host->wan); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -ENOENT; ++ ++ host->fe_base = devm_ioremap_nocache(&pdev->dev, res->start, ++ res->end - res->start + 1); ++ if (!host->fe_base) ++ return -EADDRNOTAVAIL; ++ ++ host->ppe_base = host->fe_base + 0xe00; ++ err = hnat_init_debugfs(host); ++ if (err) ++ return err; ++ ++ host->rstc = devm_reset_control_get(&pdev->dev, NULL); ++ if (IS_ERR(host->rstc)) ++ return PTR_ERR(host->rstc); ++ ++ err = hnat_start(); ++ if (err) ++ goto err_out; ++ ++ err = hnat_register_nf_hooks(); ++ if (err) ++ goto err_out; ++ ++ return 0; ++ ++err_out: ++ hnat_stop(); ++ hnat_deinit_debugfs(host); ++ return err; ++} ++ ++static int hnat_remove(struct platform_device *pdev) ++{ ++ hnat_unregister_nf_hooks(); ++ hnat_stop(); ++ hnat_deinit_debugfs(host); ++ ++ return 0; ++} ++ ++const struct of_device_id of_hnat_match[] = { ++ { .compatible = "mediatek,mt7623-hnat" }, ++ {}, ++}; ++ ++static struct platform_driver hnat_driver = { ++ .probe = hnat_probe, ++ .remove = hnat_remove, ++ .driver = { ++ .name = "mediatek_soc_hnat", ++ .of_match_table = of_hnat_match, ++ }, ++}; ++ ++module_platform_driver(hnat_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); ++MODULE_AUTHOR("John Crispin <john@phrozen.org>"); ++MODULE_DESCRIPTION("Mediatek Hardware NAT"); +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h +@@ -0,0 +1,425 @@ ++/* This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * 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. ++ * ++ * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com> ++ * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org> ++ */ ++ ++#include <linux/debugfs.h> ++#include <linux/string.h> ++#include <linux/if.h> ++#include <linux/if_ether.h> ++ ++/*--------------------------------------------------------------------------*/ ++/* Register Offset*/ ++/*--------------------------------------------------------------------------*/ ++#define PPE_GLO_CFG 0x00 ++#define PPE_FLOW_CFG 0x04 ++#define PPE_IP_PROT_CHK 0x08 ++#define PPE_IP_PROT_0 0x0C ++#define PPE_IP_PROT_1 0x10 ++#define PPE_IP_PROT_2 0x14 ++#define PPE_IP_PROT_3 0x18 ++#define PPE_TB_CFG 0x1C ++#define PPE_TB_BASE 0x20 ++#define PPE_TB_USED 0x24 ++#define PPE_BNDR 0x28 ++#define PPE_BIND_LMT_0 0x2C ++#define PPE_BIND_LMT_1 0x30 ++#define PPE_KA 0x34 ++#define PPE_UNB_AGE 0x38 ++#define PPE_BND_AGE_0 0x3C ++#define PPE_BND_AGE_1 0x40 ++#define PPE_HASH_SEED 0x44 ++#define PPE_DFT_CPORT 0x48 ++#define PPE_MCAST_PPSE 0x84 ++#define PPE_MCAST_L_0 0x88 ++#define PPE_MCAST_H_0 0x8C ++#define PPE_MCAST_L_1 0x90 ++#define PPE_MCAST_H_1 0x94 ++#define PPE_MCAST_L_2 0x98 ++#define PPE_MCAST_H_2 0x9C ++#define PPE_MCAST_L_3 0xA0 ++#define PPE_MCAST_H_3 0xA4 ++#define PPE_MCAST_L_4 0xA8 ++#define PPE_MCAST_H_4 0xAC ++#define PPE_MCAST_L_5 0xB0 ++#define PPE_MCAST_H_5 0xB4 ++#define PPE_MCAST_L_6 0xBC ++#define PPE_MCAST_H_6 0xC0 ++#define PPE_MCAST_L_7 0xC4 ++#define PPE_MCAST_H_7 0xC8 ++#define PPE_MCAST_L_8 0xCC ++#define PPE_MCAST_H_8 0xD0 ++#define PPE_MCAST_L_9 0xD4 ++#define PPE_MCAST_H_9 0xD8 ++#define PPE_MCAST_L_A 0xDC ++#define PPE_MCAST_H_A 0xE0 ++#define PPE_MCAST_L_B 0xE4 ++#define PPE_MCAST_H_B 0xE8 ++#define PPE_MCAST_L_C 0xEC ++#define PPE_MCAST_H_C 0xF0 ++#define PPE_MCAST_L_D 0xF4 ++#define PPE_MCAST_H_D 0xF8 ++#define PPE_MCAST_L_E 0xFC ++#define PPE_MCAST_H_E 0xE0 ++#define PPE_MCAST_L_F 0x100 ++#define PPE_MCAST_H_F 0x104 ++#define PPE_MTU_DRP 0x108 ++#define PPE_MTU_VLYR_0 0x10C ++#define PPE_MTU_VLYR_1 0x110 ++#define PPE_MTU_VLYR_2 0x114 ++#define PPE_VPM_TPID 0x118 ++#define PPE_CAH_CTRL 0x120 ++#define PPE_CAH_TAG_SRH 0x124 ++#define PPE_CAH_LINE_RW 0x128 ++#define PPE_CAH_WDATA 0x12C ++#define PPE_CAH_RDATA 0x130 ++ ++#define GDMA1_FWD_CFG 0x500 ++#define GDMA2_FWD_CFG 0x1500 ++/*--------------------------------------------------------------------------*/ ++/* Register Mask*/ ++/*--------------------------------------------------------------------------*/ ++/* PPE_TB_CFG mask */ ++#define TB_ETRY_NUM (0x7 << 0) /* RW */ ++#define TB_ENTRY_SIZE (0x1 << 3) /* RW */ ++#define SMA (0x3 << 4) /* RW */ ++#define NTU_AGE (0x1 << 7) /* RW */ ++#define UNBD_AGE (0x1 << 8) /* RW */ ++#define TCP_AGE (0x1 << 9) /* RW */ ++#define UDP_AGE (0x1 << 10) /* RW */ ++#define FIN_AGE (0x1 << 11) /* RW */ ++#define KA_CFG (0x3<< 12) ++#define HASH_MODE (0x3 << 14) /* RW */ ++#define XMODE (0x3 << 18) /* RW */ ++ ++/*PPE_CAH_CTRL mask*/ ++#define CAH_EN (0x1 << 0) /* RW */ ++#define CAH_X_MODE (0x1 << 9) /* RW */ ++ ++/*PPE_UNB_AGE mask*/ ++#define UNB_DLTA (0xff << 0) /* RW */ ++#define UNB_MNP (0xffff << 16) /* RW */ ++ ++/*PPE_BND_AGE_0 mask*/ ++#define UDP_DLTA (0xffff << 0) /* RW */ ++#define NTU_DLTA (0xffff << 16) /* RW */ ++ ++/*PPE_BND_AGE_1 mask*/ ++#define TCP_DLTA (0xffff << 0) /* RW */ ++#define FIN_DLTA (0xffff << 16) /* RW */ ++ ++/*PPE_KA mask*/ ++#define KA_T (0xffff << 0) /* RW */ ++#define TCP_KA (0xff << 16) /* RW */ ++#define UDP_KA (0xff << 24) /* RW */ ++ ++/*PPE_BIND_LMT_0 mask*/ ++#define QURT_LMT (0x3ff << 0) /* RW */ ++#define HALF_LMT (0x3ff << 16) /* RW */ ++ ++/*PPE_BIND_LMT_1 mask*/ ++#define FULL_LMT (0x3fff << 0) /* RW */ ++#define NTU_KA (0xff << 16) /* RW */ ++ ++/*PPE_BNDR mask*/ ++#define BIND_RATE (0xffff << 0) /* RW */ ++#define PBND_RD_PRD (0xffff << 16) /* RW */ ++ ++/*PPE_GLO_CFG mask*/ ++#define PPE_EN (0x1 << 0) /* RW */ ++#define TTL0_DRP (0x1 << 4) /* RW */ ++ ++/*GDMA1_FWD_CFG mask */ ++#define GDM1_UFRC_MASK (0x7 << 12) /* RW */ ++#define GDM1_BFRC_MASK (0x7 << 8) /*RW*/ ++#define GDM1_MFRC_MASK (0x7 << 4) /*RW*/ ++#define GDM1_OFRC_MASK (0x7 << 0) /*RW*/ ++#define GDM1_ALL_FRC_MASK (GDM1_UFRC_MASK | GDM1_BFRC_MASK | GDM1_MFRC_MASK | GDM1_OFRC_MASK) ++ ++#define GDM2_UFRC_MASK (0x7 << 12) /* RW */ ++#define GDM2_BFRC_MASK (0x7 << 8) /*RW*/ ++#define GDM2_MFRC_MASK (0x7 << 4) /*RW*/ ++#define GDM2_OFRC_MASK (0x7 << 0) /*RW*/ ++#define GDM2_ALL_FRC_MASK (GDM2_UFRC_MASK | GDM2_BFRC_MASK | GDM2_MFRC_MASK | GDM2_OFRC_MASK) ++ ++/*--------------------------------------------------------------------------*/ ++/* Descriptor Structure */ ++/*--------------------------------------------------------------------------*/ ++#define HNAT_SKB_CB(__skb) ((struct hnat_skb_cb *)&((__skb)->cb[40])) ++struct hnat_skb_cb { ++ __u16 iif; ++}; ++ ++struct hnat_unbind_info_blk { ++ u32 time_stamp:8; ++ u32 pcnt:16; /* packet count */ ++ u32 preb:1; ++ u32 pkt_type:3; ++ u32 state:2; ++ u32 udp:1; ++ u32 sta:1; /* static entry */ ++} __attribute__ ((packed)); ++ ++struct hnat_bind_info_blk { ++ u32 time_stamp:15; ++ u32 ka:1; /* keep alive */ ++ u32 vlan_layer:3; ++ u32 psn:1; /* egress packet has PPPoE session */ ++ u32 vpm:1; /* 0:ethertype remark, 1:0x8100(CR default) */ ++ u32 ps:1; /* packet sampling */ ++ u32 cah:1; /* cacheable flag */ ++ u32 rmt:1; /* remove tunnel ip header (6rd/dslite only) */ ++ u32 ttl:1; ++ u32 pkt_type:3; ++ u32 state:2; ++ u32 udp:1; ++ u32 sta:1; /* static entry */ ++} __attribute__ ((packed)); ++ ++struct hnat_info_blk2 { ++ u32 qid:4; /* QID in Qos Port */ ++ u32 fqos:1; /* force to PSE QoS port */ ++ u32 dp:3; /* force to PSE port x ++ 0:PSE,1:GSW, 2:GMAC,4:PPE,5:QDMA,7=DROP */ ++ u32 mcast:1; /* multicast this packet to CPU */ ++ u32 pcpl:1; /* OSBN */ ++ u32 mlen:1; /* 0:post 1:pre packet length in meter */ ++ u32 alen:1; /* 0:post 1:pre packet length in accounting */ ++ u32 port_mg:6; /* port meter group */ ++ u32 port_ag:6; /* port account group */ ++ u32 dscp:8; /* DSCP value */ ++} __attribute__ ((packed)); ++ ++struct hnat_ipv4_hnapt { ++ union { ++ struct hnat_bind_info_blk bfib1; ++ struct hnat_unbind_info_blk udib1; ++ u32 info_blk1; ++ }; ++ u32 sip; ++ u32 dip; ++ u16 dport; ++ u16 sport; ++ union { ++ struct hnat_info_blk2 iblk2; ++ u32 info_blk2; ++ }; ++ u32 new_sip; ++ u32 new_dip; ++ u16 new_dport; ++ u16 new_sport; ++ u32 resv1; ++ u32 resv2; ++ u32 resv3:26; ++ u32 act_dp:6; /* UDF */ ++ u16 vlan1; ++ u16 etype; ++ u32 dmac_hi; ++ u16 vlan2; ++ u16 dmac_lo; ++ u32 smac_hi; ++ u16 pppoe_id; ++ u16 smac_lo; ++} __attribute__ ((packed)); ++ ++struct foe_entry { ++ union { ++ struct hnat_unbind_info_blk udib1; ++ struct hnat_bind_info_blk bfib1; ++ struct hnat_ipv4_hnapt ipv4_hnapt; ++ }; ++}; ++ ++#define HNAT_AC_BYTE_LO(x) (0x2000 + (x * 16)) ++#define HNAT_AC_BYTE_HI(x) (0x2004 + (x * 16)) ++#define HNAT_AC_PACKET(x) (0x2008 + (x * 16)) ++#define HNAT_COUNTER_MAX 64 ++#define HNAT_AC_TIMER_INTERVAL (HZ) ++ ++struct hnat_accounting { ++ u64 bytes; ++ u64 packets; ++}; ++ ++struct hnat_priv { ++ struct device *dev; ++ void __iomem *fe_base; ++ void __iomem *ppe_base; ++ struct foe_entry *foe_table_cpu; ++ dma_addr_t foe_table_dev; ++ u8 enable; ++ u8 enable1; ++ struct dentry *root; ++ struct debugfs_regset32 *regset; ++ ++ struct timer_list ac_timer; ++ struct hnat_accounting acct[HNAT_COUNTER_MAX]; ++ ++ /*devices we plays for*/ ++ char wan[IFNAMSIZ]; ++ ++ struct reset_control *rstc; ++}; ++ ++enum FoeEntryState { ++ INVALID = 0, ++ UNBIND = 1, ++ BIND = 2, ++ FIN = 3 ++}; ++/*--------------------------------------------------------------------------*/ ++/* Common Definition*/ ++/*--------------------------------------------------------------------------*/ ++ ++#define FOE_4TB_SIZ 4096 ++#define HASH_SEED_KEY 0x12345678 ++ ++/*PPE_TB_CFG value*/ ++#define ENTRY_80B 1 ++#define ENTRY_64B 0 ++#define TABLE_1K 0 ++#define TABLE_2K 1 ++#define TABLE_4K 2 ++#define TABLE_8K 3 ++#define TABLE_16K 4 ++#define SMA_DROP 0 /* Drop the packet */ ++#define SMA_DROP2 1 /* Drop the packet */ ++#define SMA_ONLY_FWD_CPU 2 /* Only Forward to CPU */ ++#define SMA_FWD_CPU_BUILD_ENTRY 3 /* Forward to CPU and build new FOE entry */ ++#define HASH_MODE_0 0 ++#define HASH_MODE_1 1 ++#define HASH_MODE_2 2 ++#define HASH_MODE_3 3 ++ ++/*PPE_FLOW_CFG*/ ++#define BIT_FUC_FOE BIT(2) ++#define BIT_FMC_FOE BIT(1) ++#define BIT_FBC_FOE BIT(0) ++#define BIT_IPV4_NAT_EN BIT(12) ++#define BIT_IPV4_NAPT_EN BIT(13) ++#define BIT_IPV4_NAT_FRAG_EN BIT(17) ++#define BIT_IPV4_HASH_GREK BIT(19) ++ ++/*GDMA1_FWD_CFG value */ ++#define BITS_GDM1_UFRC_P_PPE (NR_PPE_PORT << 12) ++#define BITS_GDM1_BFRC_P_PPE (NR_PPE_PORT << 8) ++#define BITS_GDM1_MFRC_P_PPE (NR_PPE_PORT << 4) ++#define BITS_GDM1_OFRC_P_PPE (NR_PPE_PORT << 0) ++#define BITS_GDM1_ALL_FRC_P_PPE (BITS_GDM1_UFRC_P_PPE | BITS_GDM1_BFRC_P_PPE | BITS_GDM1_MFRC_P_PPE | BITS_GDM1_OFRC_P_PPE) ++ ++#define BITS_GDM1_UFRC_P_CPU_PDMA (NR_PDMA_PORT << 12) ++#define BITS_GDM1_BFRC_P_CPU_PDMA (NR_PDMA_PORT << 8) ++#define BITS_GDM1_MFRC_P_CPU_PDMA (NR_PDMA_PORT << 4) ++#define BITS_GDM1_OFRC_P_CPU_PDMA (NR_PDMA_PORT << 0) ++#define BITS_GDM1_ALL_FRC_P_CPU_PDMA (BITS_GDM1_UFRC_P_CPU_PDMA | BITS_GDM1_BFRC_P_CPU_PDMA | BITS_GDM1_MFRC_P_CPU_PDMA | BITS_GDM1_OFRC_P_CPU_PDMA) ++ ++#define BITS_GDM1_UFRC_P_CPU_QDMA (NR_QDMA_PORT << 12) ++#define BITS_GDM1_BFRC_P_CPU_QDMA (NR_QDMA_PORT << 8) ++#define BITS_GDM1_MFRC_P_CPU_QDMA (NR_QDMA_PORT << 4) ++#define BITS_GDM1_OFRC_P_CPU_QDMA (NR_QDMA_PORT << 0) ++#define BITS_GDM1_ALL_FRC_P_CPU_QDMA (BITS_GDM1_UFRC_P_CPU_QDMA | BITS_GDM1_BFRC_P_CPU_QDMA | BITS_GDM1_MFRC_P_CPU_QDMA | BITS_GDM1_OFRC_P_CPU_QDMA) ++ ++#define BITS_GDM1_UFRC_P_DISCARD (NR_DISCARD << 12) ++#define BITS_GDM1_BFRC_P_DISCARD (NR_DISCARD << 8) ++#define BITS_GDM1_MFRC_P_DISCARD (NR_DISCARD << 4) ++#define BITS_GDM1_OFRC_P_DISCARD (NR_DISCARD << 0) ++#define BITS_GDM1_ALL_FRC_P_DISCARD (BITS_GDM1_UFRC_P_DISCARD | BITS_GDM1_BFRC_P_DISCARD | BITS_GDM1_MFRC_P_DISCARD | BITS_GDM1_OFRC_P_DISCARD) ++ ++#define BITS_GDM2_UFRC_P_PPE (NR_PPE_PORT << 12) ++#define BITS_GDM2_BFRC_P_PPE (NR_PPE_PORT << 8) ++#define BITS_GDM2_MFRC_P_PPE (NR_PPE_PORT << 4) ++#define BITS_GDM2_OFRC_P_PPE (NR_PPE_PORT << 0) ++#define BITS_GDM2_ALL_FRC_P_PPE (BITS_GDM2_UFRC_P_PPE | BITS_GDM2_BFRC_P_PPE | BITS_GDM2_MFRC_P_PPE | BITS_GDM2_OFRC_P_PPE) ++ ++#define BITS_GDM2_UFRC_P_CPU_PDMA (NR_PDMA_PORT << 12) ++#define BITS_GDM2_BFRC_P_CPU_PDMA (NR_PDMA_PORT << 8) ++#define BITS_GDM2_MFRC_P_CPU_PDMA (NR_PDMA_PORT << 4) ++#define BITS_GDM2_OFRC_P_CPU_PDMA (NR_PDMA_PORT << 0) ++#define BITS_GDM2_ALL_FRC_P_CPU_PDMA (BITS_GDM2_UFRC_P_CPU_PDMA | BITS_GDM2_BFRC_P_CPU_PDMA | BITS_GDM2_MFRC_P_CPU_PDMA | BITS_GDM2_OFRC_P_CPU_PDMA) ++ ++#define BITS_GDM2_UFRC_P_CPU_QDMA (NR_QDMA_PORT << 12) ++#define BITS_GDM2_BFRC_P_CPU_QDMA (NR_QDMA_PORT << 8) ++#define BITS_GDM2_MFRC_P_CPU_QDMA (NR_QDMA_PORT << 4) ++#define BITS_GDM2_OFRC_P_CPU_QDMA (NR_QDMA_PORT << 0) ++#define BITS_GDM2_ALL_FRC_P_CPU_QDMA (BITS_GDM2_UFRC_P_CPU_QDMA | BITS_GDM2_BFRC_P_CPU_QDMA | BITS_GDM2_MFRC_P_CPU_QDMA | BITS_GDM2_OFRC_P_CPU_QDMA) ++ ++#define BITS_GDM2_UFRC_P_DISCARD (NR_DISCARD << 12) ++#define BITS_GDM2_BFRC_P_DISCARD (NR_DISCARD << 8) ++#define BITS_GDM2_MFRC_P_DISCARD (NR_DISCARD << 4) ++#define BITS_GDM2_OFRC_P_DISCARD (NR_DISCARD << 0) ++#define BITS_GDM2_ALL_FRC_P_DISCARD (BITS_GDM2_UFRC_P_DISCARD | BITS_GDM2_BFRC_P_DISCARD | BITS_GDM2_MFRC_P_DISCARD | BITS_GDM2_OFRC_P_DISCARD) ++ ++#define hnat_is_enabled(host) (host->enable) ++#define hnat_enabled(host) (host->enable = 1) ++#define hnat_disabled(host) (host->enable = 0) ++#define hnat_is_enabled1(host) (host->enable1) ++#define hnat_enabled1(host) (host->enable1 = 1) ++#define hnat_disabled1(host) (host->enable1 = 0) ++ ++#define entry_hnat_is_bound(e) (e->bfib1.state == BIND) ++#define entry_hnat_state(e) (e->bfib1.state) ++ ++#define skb_hnat_is_hashed(skb) (skb_hnat_entry(skb)!=0x3fff && skb_hnat_entry(skb)< FOE_4TB_SIZ) ++#define FROM_GE_LAN(skb) (HNAT_SKB_CB(skb)->iif == FOE_MAGIC_GE_LAN) ++#define FROM_GE_WAN(skb) (HNAT_SKB_CB(skb)->iif == FOE_MAGIC_GE_WAN) ++#define FROM_GE_PPD(skb) (HNAT_SKB_CB(skb)->iif == FOE_MAGIC_GE_PPD) ++#define FOE_MAGIC_GE_WAN 0x7273 ++#define FOE_MAGIC_GE_LAN 0x7272 ++#define FOE_INVALID 0xffff ++ ++#define TCP_FIN_SYN_RST 0x0C /* Ingress packet is TCP fin/syn/rst (for IPv4 NAPT/DS-Lite or IPv6 5T-route/6RD) */ ++#define UN_HIT 0x0D/* FOE Un-hit */ ++#define HIT_UNBIND 0x0E/* FOE Hit unbind */ ++#define HIT_UNBIND_RATE_REACH 0xf ++#define HNAT_HIT_BIND_OLD_DUP_HDR 0x15 ++#define HNAT_HIT_BIND_FORCE_TO_CPU 0x16 ++ ++#define HIT_BIND_KEEPALIVE_MC_NEW_HDR 0x14 ++#define HIT_BIND_KEEPALIVE_DUP_OLD_HDR 0x15 ++#define IPV4_HNAPT 0 ++#define IPV4_HNAT 1 ++#define IP_FORMAT(addr) \ ++ ((unsigned char *)&addr)[3], \ ++ ((unsigned char *)&addr)[2], \ ++ ((unsigned char *)&addr)[1], \ ++ ((unsigned char *)&addr)[0] ++ ++/*PSE Ports*/ ++#define NR_PDMA_PORT 0 ++#define NR_GMAC1_PORT 1 ++#define NR_GMAC2_PORT 2 ++#define NR_PPE_PORT 4 ++#define NR_QDMA_PORT 5 ++#define NR_DISCARD 7 ++#define IS_LAN(dev) (!strncmp(dev->name, "lan", 3)) ++#define IS_WAN(dev) (!strcmp(dev->name, host->wan)) ++#define IS_BR(dev) (!strncmp(dev->name, "br", 2)) ++#define IS_IPV4_HNAPT(x) (((x)->bfib1.pkt_type == IPV4_HNAPT) ? 1: 0) ++#define IS_IPV4_HNAT(x) (((x)->bfib1.pkt_type == IPV4_HNAT) ? 1 : 0) ++#define IS_IPV4_GRP(x) (IS_IPV4_HNAPT(x) | IS_IPV4_HNAT(x)) ++ ++#define es(entry) (entry_state[entry->bfib1.state]) ++#define ei(entry, end) (FOE_4TB_SIZ - (int)(end - entry)) ++#define pt(entry) (packet_type[entry->ipv4_hnapt.bfib1.pkt_type]) ++#define ipv4_smac(mac,e) ({mac[0]=e->ipv4_hnapt.smac_hi[3]; mac[1]=e->ipv4_hnapt.smac_hi[2];\ ++ mac[2]=e->ipv4_hnapt.smac_hi[1]; mac[3]=e->ipv4_hnapt.smac_hi[0];\ ++ mac[4]=e->ipv4_hnapt.smac_lo[1]; mac[5]=e->ipv4_hnapt.smac_lo[0];}) ++#define ipv4_dmac(mac,e) ({mac[0]=e->ipv4_hnapt.dmac_hi[3]; mac[1]=e->ipv4_hnapt.dmac_hi[2];\ ++ mac[2]=e->ipv4_hnapt.dmac_hi[1]; mac[3]=e->ipv4_hnapt.dmac_hi[0];\ ++ mac[4]=e->ipv4_hnapt.dmac_lo[1]; mac[5]=e->ipv4_hnapt.dmac_lo[0];}) ++ ++extern struct hnat_priv *host; ++ ++extern void hnat_deinit_debugfs(struct hnat_priv *h); ++extern int __init hnat_init_debugfs(struct hnat_priv *h); ++extern int hnat_register_nf_hooks(void); ++extern void hnat_unregister_nf_hooks(void); ++ +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c +@@ -0,0 +1,489 @@ ++/* This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * 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. ++ * ++ * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com> ++ * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org> ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/dma-mapping.h> ++ ++#include "hnat.h" ++ ++static const char *entry_state[] = { ++ "INVALID", ++ "UNBIND", ++ "BIND", ++ "FIN" ++}; ++ ++static const char *packet_type[] = { ++ "IPV4_HNAPT", ++ "IPV4_HNAT", ++ "IPV6_1T_ROUTE", ++ "IPV4_DSLITE", ++ "IPV6_3T_ROUTE", ++ "IPV6_5T_ROUTE", ++ "IPV6_6RD", ++}; ++ ++static int hnat_debug_show(struct seq_file *m, void *private) ++{ ++ struct hnat_priv *h = host; ++ struct foe_entry *entry, *end; ++ ++ entry = h->foe_table_cpu; ++ end = h->foe_table_cpu + FOE_4TB_SIZ; ++ while (entry < end) { ++ if (!entry->bfib1.state) { ++ entry++; ++ continue; ++ } ++ ++ if (IS_IPV4_HNAPT(entry)) { ++ __be32 saddr = htonl(entry->ipv4_hnapt.sip); ++ __be32 daddr = htonl(entry->ipv4_hnapt.dip); ++ __be32 nsaddr = htonl(entry->ipv4_hnapt.new_sip); ++ __be32 ndaddr = htonl(entry->ipv4_hnapt.new_dip); ++ unsigned char h_dest[ETH_ALEN]; ++ unsigned char h_source[ETH_ALEN]; ++ ++ *((u32*) h_source) = swab32(entry->ipv4_hnapt.smac_hi); ++ *((u16*) &h_source[4]) = swab16(entry->ipv4_hnapt.smac_lo); ++ *((u32*) h_dest) = swab32(entry->ipv4_hnapt.dmac_hi); ++ *((u16*) &h_dest[4]) = swab16(entry->ipv4_hnapt.dmac_lo); ++ seq_printf(m, ++ "(%p)0x%05x|state=%s|type=%s|%pI4:%d->%pI4:%d=>%pI4:%d->%pI4:%d|%pM=>%pM|etype=0x%04x|info1=0x%x|info2=0x%x|vlan1=%d|vlan2=%d\n", ++ (void *)h->foe_table_dev + ((void *)(entry) - (void *)h->foe_table_cpu), ++ ei(entry, end), es(entry), pt(entry), ++ &saddr, entry->ipv4_hnapt.sport, ++ &daddr, entry->ipv4_hnapt.dport, ++ &nsaddr, entry->ipv4_hnapt.new_sport, ++ &ndaddr, entry->ipv4_hnapt.new_dport, h_source, ++ h_dest, ntohs(entry->ipv4_hnapt.etype), ++ entry->ipv4_hnapt.info_blk1, ++ entry->ipv4_hnapt.info_blk2, ++ entry->ipv4_hnapt.vlan1, ++ entry->ipv4_hnapt.vlan2); ++ } else ++ seq_printf(m, "0x%05x state=%s\n", ++ ei(entry, end), es(entry)); ++ entry++; ++ } ++ ++ return 0; ++} ++ ++static int hnat_debug_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, hnat_debug_show, file->private_data); ++} ++ ++static const struct file_operations hnat_debug_fops = { ++ .open = hnat_debug_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++#define QDMA_TX_SCH_TX 0x1a14 ++ ++static ssize_t hnat_sched_show(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ int id = (int) file->private_data; ++ struct hnat_priv *h = host; ++ u32 reg = readl(h->fe_base + QDMA_TX_SCH_TX); ++ int enable; ++ int max_rate; ++ char *buf; ++ unsigned int len = 0, buf_len = 1500; ++ ssize_t ret_cnt; ++ ++ buf = kzalloc(buf_len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ ++ if (id) ++ reg >>= 16; ++ reg &= 0xffff; ++ enable = !! (reg & BIT(11)); ++ max_rate = ((reg >> 4) & 0x7f); ++ reg &= 0xf; ++ while (reg--) ++ max_rate *= 10; ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "EN\tMAX\n%d\t%d\n", enable, max_rate); ++ ++ if (len > buf_len) ++ len = buf_len; ++ ++ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ return ret_cnt; ++} ++ ++static ssize_t hnat_sched_write(struct file *file, ++ const char __user *buf, size_t length, loff_t *offset) ++{ ++ int id = (int) file->private_data; ++ struct hnat_priv *h = host; ++ char line[64]; ++ int enable, rate, exp = 0, shift = 0; ++ size_t size; ++ u32 reg = readl(h->fe_base + QDMA_TX_SCH_TX); ++ u32 val = 0; ++ ++ if (length > sizeof(line)) ++ return -EINVAL; ++ ++ if (copy_from_user(line, buf, length)) ++ return -EFAULT; ++ ++ sscanf(line, "%d %d", &enable, &rate); ++ ++ while (rate > 127) { ++ rate /= 10; ++ exp++; ++ } ++ ++ if (enable) ++ val |= BIT(11); ++ val |= (rate & 0x7f) << 4; ++ val |= exp & 0xf; ++ if (id) ++ shift = 16; ++ reg &= ~(0xffff << shift); ++ reg |= val << shift; ++ writel(reg, h->fe_base + QDMA_TX_SCH_TX); ++ ++ size = strlen(line); ++ *offset += size; ++ ++ return length; ++} ++ ++static const struct file_operations hnat_sched_fops = { ++ .open = simple_open, ++ .read = hnat_sched_show, ++ .write = hnat_sched_write, ++ .llseek = default_llseek, ++}; ++ ++#define QTX_CFG(x) (0x1800 + (x * 0x10)) ++#define QTX_SCH(x) (0x1804 + (x * 0x10)) ++ ++static ssize_t hnat_queue_show(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct hnat_priv *h = host; ++ int id = (int) file->private_data; ++ u32 reg = readl(h->fe_base + QTX_SCH(id)); ++ u32 cfg = readl(h->fe_base + QTX_CFG(id)); ++ int scheduler = !!(reg & BIT(31)); ++ int min_rate_en = !!(reg & BIT(27)); ++ int min_rate = (reg >> 20) & 0x7f; ++ int min_rate_exp = (reg >> 16) & 0xf; ++ int max_rate_en = !!(reg & BIT(11)); ++ int max_weight = (reg >> 12) & 0xf; ++ int max_rate = (reg >> 4) & 0x7f; ++ int max_rate_exp = reg & 0xf; ++ char *buf; ++ unsigned int len = 0, buf_len = 1500; ++ ssize_t ret_cnt; ++ ++ buf = kzalloc(buf_len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ while (min_rate_exp--) ++ min_rate *= 10; ++ ++ while (max_rate_exp--) ++ max_rate *= 10; ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "scheduler: %d\nhw resv: %d\nsw resv: %d\n", ++ scheduler, (cfg >> 8) & 0xff, cfg & 0xff); ++ len += scnprintf(buf + len, buf_len - len, ++ "\tEN\tRATE\t\tWEIGHT\n"); ++ len += scnprintf(buf + len, buf_len - len, ++ "max\t%d\t%8d\t%d\n", max_rate_en, max_rate, max_weight); ++ len += scnprintf(buf + len, buf_len - len, ++ "min\t%d\t%8d\t-\n", min_rate_en, min_rate); ++ ++ if (len > buf_len) ++ len = buf_len; ++ ++ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ return ret_cnt; ++} ++ ++static ssize_t hnat_queue_write(struct file *file, ++ const char __user *buf, size_t length, loff_t *offset) ++{ ++ int id = (int) file->private_data; ++ struct hnat_priv *h = host; ++ char line[64]; ++ int max_enable, max_rate, max_exp = 0; ++ int min_enable, min_rate, min_exp = 0; ++ int weight; ++ int resv; ++ int scheduler; ++ size_t size; ++ u32 reg = readl(h->fe_base + QTX_SCH(id)); ++ ++ if (length > sizeof(line)) ++ return -EINVAL; ++ ++ if (copy_from_user(line, buf, length)) ++ return -EFAULT; ++ ++ sscanf(line, "%d %d %d %d %d %d %d", &scheduler, &min_enable, &min_rate, &max_enable, &max_rate, &weight, &resv); ++ ++ while (max_rate > 127) { ++ max_rate /= 10; ++ max_exp++; ++ } ++ ++ while (min_rate > 127) { ++ min_rate /= 10; ++ min_exp++; ++ } ++ ++ reg &= 0x70000000; ++ if (scheduler) ++ reg |= BIT(31); ++ if (min_enable) ++ reg |= BIT(27); ++ reg |= (min_rate & 0x7f) << 20; ++ reg |= (min_exp & 0xf) << 16; ++ if (max_enable) ++ reg |= BIT(11); ++ reg |= (weight & 0xf) << 12; ++ reg |= (max_rate & 0x7f) << 4; ++ reg |= max_exp & 0xf; ++ writel(reg, h->fe_base + QTX_SCH(id)); ++ ++ resv &= 0xff; ++ reg = readl(h->fe_base + QTX_CFG(id)); ++ reg &= 0xffff0000; ++ reg |= (resv << 8) | resv; ++ writel(reg, h->fe_base + QTX_CFG(id)); ++ ++ size = strlen(line); ++ *offset += size; ++ ++ return length; ++} ++ ++static const struct file_operations hnat_queue_fops = { ++ .open = simple_open, ++ .read = hnat_queue_show, ++ .write = hnat_queue_write, ++ .llseek = default_llseek, ++}; ++ ++static void hnat_ac_timer_handle(unsigned long priv) ++{ ++ struct hnat_priv *h = (struct hnat_priv*) priv; ++ int i; ++ ++ for (i = 0; i < HNAT_COUNTER_MAX; i++) { ++ u32 b_hi, b_lo; ++ u64 b; ++ ++ b_lo = readl(h->fe_base + HNAT_AC_BYTE_LO(i)); ++ b_hi = readl(h->fe_base + HNAT_AC_BYTE_HI(i)); ++ b = b_hi; ++ b <<= 32; ++ b += b_lo; ++ h->acct[i].bytes += b; ++ h->acct[i].packets += readl(h->fe_base + HNAT_AC_PACKET(i)); ++ } ++ ++ mod_timer(&h->ac_timer, jiffies + HNAT_AC_TIMER_INTERVAL); ++} ++ ++static ssize_t hnat_counter_show(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct hnat_priv *h = host; ++ int id = (int) file->private_data; ++ char *buf; ++ unsigned int len = 0, buf_len = 1500; ++ ssize_t ret_cnt; ++ int id2 = id + (HNAT_COUNTER_MAX / 2); ++ ++ buf = kzalloc(buf_len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "tx pkts : %llu\ntx bytes: %llu\nrx pktks : %llu\nrx bytes : %llu\n", ++ h->acct[id].packets, h->acct[id].bytes, ++ h->acct[id2].packets, h->acct[id2].bytes); ++ ++ if (len > buf_len) ++ len = buf_len; ++ ++ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ return ret_cnt; ++} ++ ++static const struct file_operations hnat_counter_fops = { ++ .open = simple_open, ++ .read = hnat_counter_show, ++ .llseek = default_llseek, ++}; ++ ++#define dump_register(nm) \ ++{ \ ++ .name = __stringify(nm), \ ++ .offset = PPE_ ##nm , \ ++} ++ ++static const struct debugfs_reg32 hnat_regs[] = { ++ dump_register(GLO_CFG), ++ dump_register(FLOW_CFG), ++ dump_register(IP_PROT_CHK), ++ dump_register(IP_PROT_0), ++ dump_register(IP_PROT_1), ++ dump_register(IP_PROT_2), ++ dump_register(IP_PROT_3), ++ dump_register(TB_CFG), ++ dump_register(TB_BASE), ++ dump_register(TB_USED), ++ dump_register(BNDR), ++ dump_register(BIND_LMT_0), ++ dump_register(BIND_LMT_1), ++ dump_register(KA), ++ dump_register(UNB_AGE), ++ dump_register(BND_AGE_0), ++ dump_register(BND_AGE_1), ++ dump_register(HASH_SEED), ++ dump_register(DFT_CPORT), ++ dump_register(MCAST_PPSE), ++ dump_register(MCAST_L_0), ++ dump_register(MCAST_H_0), ++ dump_register(MCAST_L_1), ++ dump_register(MCAST_H_1), ++ dump_register(MCAST_L_2), ++ dump_register(MCAST_H_2), ++ dump_register(MCAST_L_3), ++ dump_register(MCAST_H_3), ++ dump_register(MCAST_L_4), ++ dump_register(MCAST_H_4), ++ dump_register(MCAST_L_5), ++ dump_register(MCAST_H_5), ++ dump_register(MCAST_L_6), ++ dump_register(MCAST_H_6), ++ dump_register(MCAST_L_7), ++ dump_register(MCAST_H_7), ++ dump_register(MCAST_L_8), ++ dump_register(MCAST_H_8), ++ dump_register(MCAST_L_9), ++ dump_register(MCAST_H_9), ++ dump_register(MCAST_L_A), ++ dump_register(MCAST_H_A), ++ dump_register(MCAST_L_B), ++ dump_register(MCAST_H_B), ++ dump_register(MCAST_L_C), ++ dump_register(MCAST_H_C), ++ dump_register(MCAST_L_D), ++ dump_register(MCAST_H_D), ++ dump_register(MCAST_L_E), ++ dump_register(MCAST_H_E), ++ dump_register(MCAST_L_F), ++ dump_register(MCAST_H_F), ++ dump_register(MTU_DRP), ++ dump_register(MTU_VLYR_0), ++ dump_register(MTU_VLYR_1), ++ dump_register(MTU_VLYR_2), ++ dump_register(VPM_TPID), ++ dump_register(VPM_TPID), ++ dump_register(CAH_CTRL), ++ dump_register(CAH_TAG_SRH), ++ dump_register(CAH_LINE_RW), ++ dump_register(CAH_WDATA), ++ dump_register(CAH_RDATA), ++}; ++ ++int __init hnat_init_debugfs(struct hnat_priv *h) ++{ ++ int ret = 0; ++ struct dentry *root; ++ struct dentry *file; ++ int i; ++ char name[16]; ++ ++ root = debugfs_create_dir("hnat", NULL); ++ if (!root) { ++ dev_err(h->dev, "%s:err at %d\n", __func__, __LINE__); ++ ret = -ENOMEM; ++ goto err0; ++ } ++ h->root = root; ++ h->regset = kzalloc(sizeof(*h->regset), GFP_KERNEL); ++ if (!h->regset) { ++ dev_err(h->dev, "%s:err at %d\n", __func__, __LINE__); ++ ret = -ENOMEM; ++ goto err1; ++ } ++ h->regset->regs = hnat_regs; ++ h->regset->nregs = ARRAY_SIZE(hnat_regs); ++ h->regset->base = h->ppe_base; ++ ++ file = debugfs_create_regset32("regdump", S_IRUGO, root, h->regset); ++ if (!file) { ++ dev_err(h->dev, "%s:err at %d\n", __func__, __LINE__); ++ ret = -ENOMEM; ++ goto err1; ++ } ++ debugfs_create_file("all_entry", S_IRUGO, root, h, &hnat_debug_fops); ++ for (i = 0; i < HNAT_COUNTER_MAX / 2; i++) { ++ snprintf(name, sizeof(name), "counter%d", i); ++ debugfs_create_file(name, S_IRUGO, root, (void *)i, &hnat_counter_fops); ++ } ++ ++ for (i = 0; i < 2; i++) { ++ snprintf(name, sizeof(name), "scheduler%d", i); ++ debugfs_create_file(name, S_IRUGO, root, (void *)i, &hnat_sched_fops); ++ } ++ ++ for (i = 0; i < 16; i++) { ++ snprintf(name, sizeof(name), "queue%d", i); ++ debugfs_create_file(name, S_IRUGO, root, (void *)i, &hnat_queue_fops); ++ } ++ ++ setup_timer(&h->ac_timer, hnat_ac_timer_handle, (unsigned long) h); ++ mod_timer(&h->ac_timer, jiffies + HNAT_AC_TIMER_INTERVAL); ++ ++ return 0; ++ ++ err1: ++ debugfs_remove_recursive(root); ++ err0: ++ return ret; ++} ++ ++void hnat_deinit_debugfs(struct hnat_priv *h) ++{ ++ del_timer(&h->ac_timer); ++ debugfs_remove_recursive(h->root); ++ h->root = NULL; ++} +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c +@@ -0,0 +1,289 @@ ++/* This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * 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. ++ * ++ * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com> ++ * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org> ++ */ ++ ++#include <linux/netfilter_bridge.h> ++ ++#include <net/arp.h> ++#include <net/neighbour.h> ++#include <net/netfilter/nf_conntrack_helper.h> ++ ++#include "nf_hnat_mtk.h" ++#include "hnat.h" ++ ++#include "../mtk_eth_soc.h" ++ ++static unsigned int skb_to_hnat_info(struct sk_buff *skb, ++ const struct net_device *dev, ++ struct foe_entry *foe) ++{ ++ struct foe_entry entry = { 0 }; ++ int lan = IS_LAN(dev); ++ struct ethhdr *eth; ++ struct iphdr *iph; ++ struct tcphdr *tcph; ++ struct udphdr *udph; ++ int tcp = 0; ++ int ipv4 = 0; ++ u32 gmac; ++ ++ eth = eth_hdr(skb); ++ switch (ntohs(eth->h_proto)) { ++ case ETH_P_IP: ++ ipv4 = 1; ++ break; ++ ++ default: ++ return -1; ++ } ++ ++ iph = ip_hdr(skb); ++ switch (iph->protocol) { ++ case IPPROTO_TCP: ++ tcph = tcp_hdr(skb); ++ tcp = 1; ++ break; ++ ++ case IPPROTO_UDP: ++ udph = udp_hdr(skb); ++ break; ++ ++ default: ++ return -1; ++ } ++ ++ entry.ipv4_hnapt.etype = htons(ETH_P_IP); ++ ++ if (lan) { ++ entry.ipv4_hnapt.etype = htons(ETH_P_8021Q); ++ entry.bfib1.vlan_layer = 1; ++ entry.ipv4_hnapt.vlan1 = BIT(dev->name[3] - '0'); ++ } ++ ++ if (dev->priv_flags & IFF_802_1Q_VLAN) { ++ struct vlan_dev_priv *vlan = vlan_dev_priv(dev); ++ ++ entry.ipv4_hnapt.etype = htons(ETH_P_8021Q); ++ entry.bfib1.vlan_layer = 1; ++ if (lan) ++ entry.ipv4_hnapt.vlan2 = vlan->vlan_id; ++ else ++ entry.ipv4_hnapt.vlan1 = vlan->vlan_id; ++ } ++ ++ entry.ipv4_hnapt.dmac_hi = swab32(*((u32*) eth->h_dest)); ++ entry.ipv4_hnapt.dmac_lo = swab16(*((u16*) ð->h_dest[4])); ++ entry.ipv4_hnapt.smac_hi = swab32(*((u32*) eth->h_source)); ++ entry.ipv4_hnapt.smac_lo = swab16(*((u16*) ð->h_source[4])); ++ entry.ipv4_hnapt.pppoe_id = 0; ++ entry.bfib1.psn = 0; ++ entry.ipv4_hnapt.bfib1.vpm = 1; ++ ++ if (ipv4) ++ entry.ipv4_hnapt.bfib1.pkt_type = IPV4_HNAPT; ++ ++ entry.ipv4_hnapt.new_sip = ntohl(iph->saddr); ++ entry.ipv4_hnapt.new_dip = ntohl(iph->daddr); ++ entry.ipv4_hnapt.iblk2.dscp = iph->tos; ++#if defined(CONFIG_NET_MEDIATEK_HW_QOS) ++ entry.ipv4_hnapt.iblk2.qid = skb->mark & 0x7; ++ if (lan) ++ entry.ipv4_hnapt.iblk2.qid += 8; ++ entry.ipv4_hnapt.iblk2.fqos = 1; ++#endif ++ if (tcp) { ++ entry.ipv4_hnapt.new_sport = ntohs(tcph->source); ++ entry.ipv4_hnapt.new_dport = ntohs(tcph->dest); ++ entry.ipv4_hnapt.bfib1.udp = 0; ++ } else { ++ entry.ipv4_hnapt.new_sport = ntohs(udph->source); ++ entry.ipv4_hnapt.new_dport = ntohs(udph->dest); ++ entry.ipv4_hnapt.bfib1.udp = 1; ++ } ++ ++ if (IS_LAN(dev)) ++ gmac = NR_GMAC1_PORT; ++ else if (IS_WAN(dev)) ++ gmac = NR_GMAC2_PORT; ++ ++ if (is_multicast_ether_addr(ð->h_dest[0])) ++ entry.ipv4_hnapt.iblk2.mcast = 1; ++ else ++ entry.ipv4_hnapt.iblk2.mcast = 0; ++ ++ entry.ipv4_hnapt.iblk2.dp = gmac; ++ entry.ipv4_hnapt.iblk2.port_mg = 0x3f; ++ entry.ipv4_hnapt.iblk2.port_ag = (skb->mark >> 3) & 0x1f; ++ if (IS_LAN(dev)) ++ entry.ipv4_hnapt.iblk2.port_ag += 32; ++ entry.bfib1.time_stamp = readl((host->fe_base + 0x0010)) & (0xFFFF); ++ entry.ipv4_hnapt.bfib1.ttl = 1; ++ entry.ipv4_hnapt.bfib1.cah = 1; ++ entry.ipv4_hnapt.bfib1.ka = 1; ++ entry.bfib1.state = BIND; ++ ++ entry.ipv4_hnapt.sip = foe->ipv4_hnapt.sip; ++ entry.ipv4_hnapt.dip = foe->ipv4_hnapt.dip; ++ entry.ipv4_hnapt.sport = foe->ipv4_hnapt.sport; ++ entry.ipv4_hnapt.dport = foe->ipv4_hnapt.dport; ++ ++ memcpy(foe, &entry, sizeof(entry)); ++ ++ return 0; ++} ++ ++static unsigned int mtk_hnat_nf_post_routing(struct sk_buff *skb, ++ const struct net_device *out, ++ unsigned int (*fn)(struct sk_buff *, const struct net_device *), ++ const char *func) ++{ ++ struct foe_entry *entry; ++ struct nf_conn *ct; ++ enum ip_conntrack_info ctinfo; ++ const struct nf_conn_help *help; ++ ++ if ((skb->mark & 0x7) < 4) ++ return 0; ++ ++ ct = nf_ct_get(skb, &ctinfo); ++ if (!ct) ++ return 0; ++ ++ /* rcu_read_lock()ed by nf_hook_slow */ ++ help = nfct_help(ct); ++ if (help && rcu_dereference(help->helper)) ++ return 0; ++ ++ if ((FROM_GE_WAN(skb) || FROM_GE_LAN(skb)) && ++ skb_hnat_is_hashed(skb) && ++ (skb_hnat_reason(skb) == HIT_BIND_KEEPALIVE_DUP_OLD_HDR)) ++ return -1; ++ ++ if ((IS_LAN(out) && FROM_GE_WAN(skb)) || ++ (IS_WAN(out) && FROM_GE_LAN(skb))) { ++ if (!skb_hnat_is_hashed(skb)) ++ return 0; ++ ++ entry = &host->foe_table_cpu[skb_hnat_entry(skb)]; ++ if (entry_hnat_is_bound(entry)) ++ return 0; ++ ++ if (skb_hnat_reason(skb) == HIT_UNBIND_RATE_REACH && ++ skb_hnat_alg(skb) == 0) { ++ if (fn && fn(skb, out)) ++ return 0; ++ skb_to_hnat_info(skb, out, entry); ++ } ++ } ++ ++ return 0; ++} ++ ++static unsigned int mtk_hnat_nf_pre_routing(void *priv, ++ struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ if (IS_WAN(state->in)) ++ HNAT_SKB_CB(skb)->iif = FOE_MAGIC_GE_WAN; ++ else if (IS_LAN(state->in)) ++ HNAT_SKB_CB(skb)->iif = FOE_MAGIC_GE_LAN; ++ else if (!IS_BR(state->in)) ++ HNAT_SKB_CB(skb)->iif = FOE_INVALID; ++ ++ return NF_ACCEPT; ++} ++ ++static unsigned int hnat_get_nexthop(struct sk_buff *skb, const struct net_device *out) { ++ ++ u32 nexthop; ++ struct neighbour *neigh; ++ struct dst_entry *dst = skb_dst(skb); ++ struct rtable *rt = (struct rtable *)dst; ++ struct net_device *dev = (__force struct net_device *)out; ++ ++ rcu_read_lock_bh(); ++ nexthop = (__force u32) rt_nexthop(rt, ip_hdr(skb)->daddr); ++ neigh = __ipv4_neigh_lookup_noref(dev, nexthop); ++ if (unlikely(!neigh)) { ++ dev_err(host->dev, "%s:++ no neigh\n", __func__); ++ return -1; ++ } ++ ++ /* why do we get all zero ethernet address ? */ ++ if (!is_valid_ether_addr(neigh->ha)){ ++ rcu_read_unlock_bh(); ++ return -1; ++ } ++ ++ memcpy(eth_hdr(skb)->h_dest, neigh->ha, ETH_ALEN); ++ memcpy(eth_hdr(skb)->h_source, out->dev_addr, ETH_ALEN); ++ ++ rcu_read_unlock_bh(); ++ ++ return 0; ++} ++ ++static unsigned int mtk_hnat_ipv4_nf_post_routing(void *priv, ++ struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ if (!mtk_hnat_nf_post_routing(skb, state->out, hnat_get_nexthop, __func__)) ++ return NF_ACCEPT; ++ ++ return NF_DROP; ++} ++ ++static unsigned int mtk_hnat_br_nf_post_routing(void *priv, ++ struct sk_buff *skb, ++ const struct nf_hook_state *state) ++{ ++ if (!mtk_hnat_nf_post_routing(skb, state->out , 0, __func__)) ++ return NF_ACCEPT; ++ ++ return NF_DROP; ++} ++ ++static struct nf_hook_ops mtk_hnat_nf_ops[] __read_mostly = { ++ { ++ .hook = mtk_hnat_nf_pre_routing, ++ .pf = NFPROTO_IPV4, ++ .hooknum = NF_INET_PRE_ROUTING, ++ .priority = NF_IP_PRI_FIRST, ++ }, { ++ .hook = mtk_hnat_ipv4_nf_post_routing, ++ .pf = NFPROTO_IPV4, ++ .hooknum = NF_INET_POST_ROUTING, ++ .priority = NF_IP_PRI_LAST, ++ }, { ++ .hook = mtk_hnat_nf_pre_routing, ++ .pf = NFPROTO_BRIDGE, ++ .hooknum = NF_BR_PRE_ROUTING, ++ .priority = NF_BR_PRI_FIRST, ++ }, { ++ .hook = mtk_hnat_br_nf_post_routing, ++ .pf = NFPROTO_BRIDGE, ++ .hooknum = NF_BR_POST_ROUTING, ++ .priority = NF_BR_PRI_LAST - 1, ++ }, ++}; ++ ++int hnat_register_nf_hooks(void) ++{ ++ return nf_register_hooks(mtk_hnat_nf_ops, ++ ARRAY_SIZE(mtk_hnat_nf_ops)); ++} ++ ++void hnat_unregister_nf_hooks(void) ++{ ++ nf_unregister_hooks(mtk_hnat_nf_ops, ++ ARRAY_SIZE(mtk_hnat_nf_ops)); ++} +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h +@@ -0,0 +1,44 @@ ++/* This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * 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. ++ * ++ * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com> ++ * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org> ++ */ ++ ++#ifndef NF_HNAT_MTK_H ++#define NF_HNAT_MTK_H ++ ++#include <asm/dma-mapping.h> ++#include <linux/netdevice.h> ++ ++#define HNAT_SKB_CB2(__skb) ((struct hnat_skb_cb2 *)&((__skb)->cb[44])) ++struct hnat_skb_cb2 { ++ __u32 magic; ++}; ++ ++struct hnat_desc { ++ u32 entry:14; ++ u32 crsn:5; ++ u32 sport:4; ++ u32 alg:9; ++} __attribute__ ((packed)); ++ ++#define skb_hnat_magic(skb) (((struct hnat_desc *)(skb->head))->magic) ++#define skb_hnat_reason(skb) (((struct hnat_desc *)(skb->head))->crsn) ++#define skb_hnat_entry(skb) (((struct hnat_desc *)(skb->head))->entry) ++#define skb_hnat_sport(skb) (((struct hnat_desc *)(skb->head))->sport) ++#define skb_hnat_alg(skb) (((struct hnat_desc *)(skb->head))->alg) ++ ++u32 hnat_tx(struct sk_buff *skb); ++u32 hnat_set_skb_info(struct sk_buff *skb, u32 *rxd); ++u32 hnat_reg(struct net_device *, void __iomem *); ++u32 hnat_unreg(void); ++ ++#endif ++ diff --git a/target/linux/mediatek/patches-4.9/0091-net-next-mediatek-fix-DQL-support.patch b/target/linux/mediatek/patches-4.9/0027-net-next-mediatek-fix-DQL-support.patch index 6e65d27..d21c8ee 100644 --- a/target/linux/mediatek/patches-4.9/0091-net-next-mediatek-fix-DQL-support.patch +++ b/target/linux/mediatek/patches-4.9/0027-net-next-mediatek-fix-DQL-support.patch @@ -1,7 +1,7 @@ -From 81cdbda2a08375b9d5915567d2210bf2433e7332 Mon Sep 17 00:00:00 2001 +From f974e397b806f7b16d11cc1542538616291924f1 Mon Sep 17 00:00:00 2001 From: John Crispin <john@phrozen.org> Date: Sat, 23 Apr 2016 11:57:21 +0200 -Subject: [PATCH 081/102] net-next: mediatek: fix DQL support +Subject: [PATCH 27/57] net-next: mediatek: fix DQL support The MTK ethernet core has 2 MACs both sitting on the same DMA ring. The current code will assign the TX traffic of each MAC to its own DQL. This @@ -13,12 +13,12 @@ using the DMA. Signed-off-by: John Crispin <john@phrozen.org> --- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 33 ++++++++++++++++----------- - 1 file changed, 20 insertions(+), 13 deletions(-) + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 35 +++++++++++++++++------------ + 1 file changed, 21 insertions(+), 14 deletions(-) --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -706,7 +706,16 @@ static int mtk_tx_map(struct sk_buff *sk +@@ -710,7 +710,16 @@ static int mtk_tx_map(struct sk_buff *sk WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) | (!nr_frags * TX_DMA_LS0))); @@ -36,7 +36,7 @@ Signed-off-by: John Crispin <john@phrozen.org> skb_tx_timestamp(skb); ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2); -@@ -998,21 +1007,18 @@ static int mtk_poll_tx(struct mtk_eth *e +@@ -1002,21 +1011,18 @@ static int mtk_poll_tx(struct mtk_eth *e struct mtk_tx_dma *desc; struct sk_buff *skb; struct mtk_tx_buf *tx_buf; @@ -60,9 +60,9 @@ Signed-off-by: John Crispin <john@phrozen.org> - while ((cpu != dma) && budget) { + while ((cpu != dma) && done < budget) { u32 next_cpu = desc->txd2; - int mac; + int mac = 0; -@@ -1032,9 +1038,8 @@ static int mtk_poll_tx(struct mtk_eth *e +@@ -1035,9 +1041,8 @@ static int mtk_poll_tx(struct mtk_eth *e } if (skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC) { @@ -74,7 +74,7 @@ Signed-off-by: John Crispin <john@phrozen.org> } mtk_tx_unmap(eth, tx_buf); -@@ -1046,11 +1051,13 @@ static int mtk_poll_tx(struct mtk_eth *e +@@ -1049,11 +1054,13 @@ static int mtk_poll_tx(struct mtk_eth *e mtk_w32(eth, cpu, MTK_QTX_CRX_PTR); diff --git a/target/linux/mediatek/patches-4.9/0092-dsa2.patch b/target/linux/mediatek/patches-4.9/0028-net-next-dsa-add-Mediatek-tag-RX-TX-handler.patch index a5b4242..2ba1cb8 100644 --- a/target/linux/mediatek/patches-4.9/0092-dsa2.patch +++ b/target/linux/mediatek/patches-4.9/0028-net-next-dsa-add-Mediatek-tag-RX-TX-handler.patch @@ -1,21 +1,7 @@ -From patchwork Wed Mar 29 09:38:20 2017 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [net-next,v3,2/5] net-next: dsa: add Mediatek tag RX/TX handler -From: sean.wang@mediatek.com -X-Patchwork-Id: 9651099 -Message-Id: <1490780303-18598-3-git-send-email-sean.wang@mediatek.com> -To: <andrew@lunn.ch>, <f.fainelli@gmail.com>, - <vivien.didelot@savoirfairelinux.com>, <matthias.bgg@gmail.com>, - <robh+dt@kernel.org>, <mark.rutland@arm.com> -Cc: devicetree@vger.kernel.org, Landen.Chao@mediatek.com, keyhaede@gmail.com, - netdev@vger.kernel.org, sean.wang@mediatek.com, - linux-kernel@vger.kernel.org, - linux-mediatek@lists.infradead.org, objelf@gmail.com, davem@davemloft.net -Date: Wed, 29 Mar 2017 17:38:20 +0800 - +From 5c01c03920c63630864d2b8641924a8c7c6cb62f Mon Sep 17 00:00:00 2001 From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 29 Mar 2017 17:38:20 +0800 +Subject: [PATCH 28/57] net-next: dsa: add Mediatek tag RX/TX handler Add the support for the 4-bytes tag for DSA port distinguishing inserted allowing receiving and transmitting the packet via the particular port. diff --git a/target/linux/mediatek/patches-4.9/0092-dsa3.patch b/target/linux/mediatek/patches-4.9/0029-net-next-ethernet-mediatek-add-CDM-able-to-recognize.patch index 385add1..5c7e6e4 100644 --- a/target/linux/mediatek/patches-4.9/0092-dsa3.patch +++ b/target/linux/mediatek/patches-4.9/0029-net-next-ethernet-mediatek-add-CDM-able-to-recognize.patch @@ -1,23 +1,8 @@ -From patchwork Wed Mar 29 09:38:21 2017 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [net-next, v3, - 3/5] net-next: ethernet: mediatek: add CDM able to recognize the tag - for DSA -From: sean.wang@mediatek.com -X-Patchwork-Id: 9651091 -Message-Id: <1490780303-18598-4-git-send-email-sean.wang@mediatek.com> -To: <andrew@lunn.ch>, <f.fainelli@gmail.com>, - <vivien.didelot@savoirfairelinux.com>, <matthias.bgg@gmail.com>, - <robh+dt@kernel.org>, <mark.rutland@arm.com> -Cc: devicetree@vger.kernel.org, Landen.Chao@mediatek.com, keyhaede@gmail.com, - netdev@vger.kernel.org, sean.wang@mediatek.com, - linux-kernel@vger.kernel.org, - linux-mediatek@lists.infradead.org, objelf@gmail.com, davem@davemloft.net -Date: Wed, 29 Mar 2017 17:38:21 +0800 - +From de3c04b820e1d396bf12e88ea87271a84f6fedb7 Mon Sep 17 00:00:00 2001 From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 29 Mar 2017 17:38:21 +0800 +Subject: [PATCH 29/57] net-next: ethernet: mediatek: add CDM able to recognize + the tag for DSA The patch adds the setup for allowing CDM can recognize these packets with carrying port-distinguishing tag. Otherwise, these tagging packets will be @@ -35,9 +20,9 @@ Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1855,6 +1855,12 @@ static int mtk_hw_init(struct mtk_eth *e - /* GE2, Force 1000M/FD, FC ON */ - mtk_w32(eth, MAC_MCR_FIXED_LINK, MTK_MAC_MCR(1)); +@@ -1864,6 +1864,12 @@ static int mtk_hw_init(struct mtk_eth *e + val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); + mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); + /* Indicates CDM to parse the MTK special tag from CPU + * which also is working out for untag packets. @@ -50,9 +35,9 @@ Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -70,6 +70,10 @@ - /* Frame Engine Interrupt Grouping Register */ - #define MTK_FE_INT_GRP 0x20 +@@ -74,6 +74,10 @@ + #define MTK_CDMQ_IG_CTRL 0x1400 + #define MTK_CDMQ_STAG_EN BIT(0) +/* CDMP Ingress Control Register */ +#define MTK_CDMQ_IG_CTRL 0x1400 diff --git a/target/linux/mediatek/patches-4.9/0092-dsa5.patch b/target/linux/mediatek/patches-4.9/0030-net-next-dsa-add-dsa-support-for-Mediatek-MT7530-swi.patch index 63a40d0..47a0683 100644 --- a/target/linux/mediatek/patches-4.9/0092-dsa5.patch +++ b/target/linux/mediatek/patches-4.9/0030-net-next-dsa-add-dsa-support-for-Mediatek-MT7530-swi.patch @@ -1,22 +1,8 @@ -From patchwork Wed Mar 29 09:38:23 2017 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [net-next, v3, - 5/5] net-next: dsa: add dsa support for Mediatek MT7530 switch -From: sean.wang@mediatek.com -X-Patchwork-Id: 9651095 -Message-Id: <1490780303-18598-6-git-send-email-sean.wang@mediatek.com> -To: <andrew@lunn.ch>, <f.fainelli@gmail.com>, - <vivien.didelot@savoirfairelinux.com>, <matthias.bgg@gmail.com>, - <robh+dt@kernel.org>, <mark.rutland@arm.com> -Cc: devicetree@vger.kernel.org, Landen.Chao@mediatek.com, keyhaede@gmail.com, - netdev@vger.kernel.org, sean.wang@mediatek.com, - linux-kernel@vger.kernel.org, - linux-mediatek@lists.infradead.org, objelf@gmail.com, davem@davemloft.net -Date: Wed, 29 Mar 2017 17:38:23 +0800 - +From 6a0a62dec3c582db4260f411294770448efc3d6c Mon Sep 17 00:00:00 2001 From: Sean Wang <sean.wang@mediatek.com> +Date: Wed, 29 Mar 2017 17:38:23 +0800 +Subject: [PATCH 30/57] net-next: dsa: add dsa support for Mediatek MT7530 + switch MT7530 is a 7-ports Gigabit Ethernet Switch that could be found on Mediatek router platforms such as MT7623A or MT7623N platform which diff --git a/target/linux/mediatek/patches-4.9/0093-dsa-compat.patch b/target/linux/mediatek/patches-4.9/0031-net-dsa-dsa-api-compat.patch index f69078c..9e52be8 100644 --- a/target/linux/mediatek/patches-4.9/0093-dsa-compat.patch +++ b/target/linux/mediatek/patches-4.9/0031-net-dsa-dsa-api-compat.patch @@ -1,3 +1,17 @@ +From a319687ac18dcc557a88054282508e061ad8495f Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 14:42:19 +0200 +Subject: [PATCH 31/57] net: dsa: dsa api compat + +make the latest driver work on the old API + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/dsa/mt7530.c | 14 ++++++++------ + drivers/net/dsa/mt7530.h | 2 ++ + net/dsa/tag_mtk.c | 2 +- + 3 files changed, 11 insertions(+), 7 deletions(-) + --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -834,6 +834,7 @@ mt7530_port_bridge_join(struct dsa_switc diff --git a/target/linux/mediatek/patches-4.9/0095-ephy.patch b/target/linux/mediatek/patches-4.9/0032-net-dsa-mediatek-add-support-for-GMAC2-wired-to-ext-.patch index dc88ca2..6c96b06 100644 --- a/target/linux/mediatek/patches-4.9/0095-ephy.patch +++ b/target/linux/mediatek/patches-4.9/0032-net-dsa-mediatek-add-support-for-GMAC2-wired-to-ext-.patch @@ -1,3 +1,15 @@ +From 52e9ce30a2b3c414e0efb20632fefa7cfc5096e6 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 14:44:18 +0200 +Subject: [PATCH 32/57] net: dsa: mediatek: add support for GMAC2 wired to ext + phy + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/dsa/mt7530.c | 5 +++++ + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 +++ + 2 files changed, 8 insertions(+) + --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -629,6 +629,11 @@ mt7530_setup(struct dsa_switch *ds) diff --git a/target/linux/mediatek/patches-4.9/0096-dsa-multi-cpu.patch b/target/linux/mediatek/patches-4.9/0033-net-dsa-add-multi-gmac-support.patch index 6394e14..8ff2bed 100644 --- a/target/linux/mediatek/patches-4.9/0096-dsa-multi-cpu.patch +++ b/target/linux/mediatek/patches-4.9/0033-net-dsa-add-multi-gmac-support.patch @@ -1,3 +1,17 @@ +From cce5dd6034ed1651ee25c910edee708e6b84a44a Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 14:45:08 +0200 +Subject: [PATCH 33/57] net: dsa: add multi gmac support + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/dsa/mt7530.c | 10 +--------- + include/net/dsa.h | 21 ++++++++++++++++++++- + net/dsa/dsa2.c | 40 +++++++++++++++++++++++++++++++++------- + net/dsa/dsa_priv.h | 1 + + net/dsa/slave.c | 26 ++++++++++++++++---------- + 5 files changed, 71 insertions(+), 27 deletions(-) + --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -996,15 +996,7 @@ err: diff --git a/target/linux/mediatek/patches-4.9/0097-dsa-mt7530.patch b/target/linux/mediatek/patches-4.9/0034-net-dsa-mediatek-add-dual-gmac-support.patch index 26eff60..ae06146 100644 --- a/target/linux/mediatek/patches-4.9/0097-dsa-mt7530.patch +++ b/target/linux/mediatek/patches-4.9/0034-net-dsa-mediatek-add-dual-gmac-support.patch @@ -1,3 +1,13 @@ +From dcb751a52b2ee69c16db2fef8f92a96ab13b6bb4 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 14:45:34 +0200 +Subject: [PATCH 34/57] net: dsa: mediatek: add dual gmac support + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/dsa/mt7530.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -627,7 +627,7 @@ mt7530_setup(struct dsa_switch *ds) diff --git a/target/linux/mediatek/patches-4.9/0035-net-mediatek-disable-RX-VLan-offloading.patch b/target/linux/mediatek/patches-4.9/0035-net-mediatek-disable-RX-VLan-offloading.patch new file mode 100644 index 0000000..36321c5 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0035-net-mediatek-disable-RX-VLan-offloading.patch @@ -0,0 +1,47 @@ +From 35b83b85e752a6660b92f08c0fb912308f25cf6d Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 15:56:40 +0200 +Subject: [PATCH 35/57] net: mediatek: disable RX VLan offloading + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 9 ++++++--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 -- + 2 files changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -643,8 +643,8 @@ static int mtk_tx_map(struct sk_buff *sk + txd4 |= TX_DMA_CHKSUM; + + /* VLAN header offload */ +- if (skb_vlan_tag_present(skb)) +- txd4 |= TX_DMA_INS_VLAN | skb_vlan_tag_get(skb); ++// if (skb_vlan_tag_present(skb)) ++// txd4 |= TX_DMA_INS_VLAN | skb_vlan_tag_get(skb); + + mapped_addr = dma_map_single(eth->dev, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); +@@ -1874,7 +1874,10 @@ static int mtk_hw_init(struct mtk_eth *e + mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); + + /* Enable RX VLan Offloading */ +- mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); ++ if (MTK_HW_FEATURES & NETIF_F_HW_VLAN_CTAG_RX) ++ mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); ++ else ++ mtk_w32(eth, 0, MTK_CDMP_EG_CTRL); + + /* disable delay and normal interrupt */ + mtk_w32(eth, 0, MTK_QDMA_DELAY_INT); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -34,8 +34,6 @@ + NETIF_MSG_TX_ERR) + #define MTK_HW_FEATURES (NETIF_F_IP_CSUM | \ + NETIF_F_RXCSUM | \ +- NETIF_F_HW_VLAN_CTAG_TX | \ +- NETIF_F_HW_VLAN_CTAG_RX | \ + NETIF_F_SG | NETIF_F_TSO | \ + NETIF_F_TSO6 | \ + NETIF_F_IPV6_CSUM) diff --git a/target/linux/mediatek/patches-4.9/0036-net-next-mediatek-fix-typos-inside-the-header-file.patch b/target/linux/mediatek/patches-4.9/0036-net-next-mediatek-fix-typos-inside-the-header-file.patch new file mode 100644 index 0000000..e96374f --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0036-net-next-mediatek-fix-typos-inside-the-header-file.patch @@ -0,0 +1,25 @@ +From bf25fbdc7dfb256f267725336e29e232aadd5123 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Fri, 21 Jul 2017 08:43:58 +0200 +Subject: [PATCH 36/57] net-next: mediatek: fix typos inside the header file + +Trivial patch fixing 2 typos. + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -525,8 +525,8 @@ struct mtk_rx_ring { + * @pctl: The register map pointing at the range used to setup + * GMAC port drive/slew values + * @dma_refcnt: track how many netdevs are using the DMA engine +- * @tx_ring: Pointer to the memore holding info about the TX ring +- * @rx_ring: Pointer to the memore holding info about the RX ring ++ * @tx_ring: Pointer to the memory holding info about the TX ring ++ * @rx_ring: Pointer to the memory holding info about the RX ring + * @tx_napi: The TX NAPI struct + * @rx_napi: The RX NAPI struct + * @scratch_ring: Newer SoCs need memory for a second HW managed TX ring diff --git a/target/linux/mediatek/patches-4.9/0037-net-next-mediatek-bring-up-QDMA-RX-ring-0.patch b/target/linux/mediatek/patches-4.9/0037-net-next-mediatek-bring-up-QDMA-RX-ring-0.patch new file mode 100644 index 0000000..9d6a089 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0037-net-next-mediatek-bring-up-QDMA-RX-ring-0.patch @@ -0,0 +1,128 @@ +From 047a4e7b17322c1b32d8db32a0df9899cb4963a3 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Fri, 21 Jul 2017 08:48:38 +0200 +Subject: [PATCH 37/57] net-next: mediatek: bring up QDMA RX ring 0 + +This patch is in peparation for adding HW flow and QoS offloading. For +those features to work, the driver needs to bring up the first QDMA RX +ring. This ring is used by the PPE offloading HW. + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 38 ++++++++++++++++++++--------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 +++ + 2 files changed, 30 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1224,11 +1224,21 @@ static void mtk_tx_clean(struct mtk_eth + + static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) + { +- struct mtk_rx_ring *ring = ð->rx_ring[ring_no]; ++ struct mtk_rx_ring *ring; + int rx_data_len, rx_dma_size; + int i; ++ u32 offset = 0; + +- if (rx_flag == MTK_RX_FLAGS_HWLRO) { ++ if (rx_flag & MTK_RX_FLAGS_QDMA) { ++ if (ring_no) ++ return -EINVAL; ++ ring = ð->rx_ring_qdma; ++ offset = 0x1000; ++ } else { ++ ring = ð->rx_ring[ring_no]; ++ } ++ ++ if (rx_flag & MTK_RX_FLAGS_HWLRO) { + rx_data_len = MTK_MAX_LRO_RX_LENGTH; + rx_dma_size = MTK_HW_LRO_DMA_SIZE; + } else { +@@ -1276,17 +1286,16 @@ static int mtk_rx_alloc(struct mtk_eth * + */ + wmb(); + +- mtk_w32(eth, ring->phys, MTK_PRX_BASE_PTR_CFG(ring_no)); +- mtk_w32(eth, rx_dma_size, MTK_PRX_MAX_CNT_CFG(ring_no)); +- mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg); +- mtk_w32(eth, MTK_PST_DRX_IDX_CFG(ring_no), MTK_PDMA_RST_IDX); ++ mtk_w32(eth, ring->phys, MTK_PRX_BASE_PTR_CFG(ring_no) + offset); ++ mtk_w32(eth, rx_dma_size, MTK_PRX_MAX_CNT_CFG(ring_no) + offset); ++ mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg + offset); ++ mtk_w32(eth, MTK_PST_DRX_IDX_CFG(ring_no), MTK_PDMA_RST_IDX + offset); + + return 0; + } + +-static void mtk_rx_clean(struct mtk_eth *eth, int ring_no) ++static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring) + { +- struct mtk_rx_ring *ring = ð->rx_ring[ring_no]; + int i; + + if (ring->data && ring->dma) { +@@ -1612,6 +1621,10 @@ static int mtk_dma_init(struct mtk_eth * + if (err) + return err; + ++ err = mtk_rx_alloc(eth, 0, MTK_RX_FLAGS_QDMA); ++ if (err) ++ return err; ++ + err = mtk_rx_alloc(eth, 0, MTK_RX_FLAGS_NORMAL); + if (err) + return err; +@@ -1651,12 +1664,13 @@ static void mtk_dma_free(struct mtk_eth + eth->phy_scratch_ring = 0; + } + mtk_tx_clean(eth); +- mtk_rx_clean(eth, 0); ++ mtk_rx_clean(eth, ð->rx_ring[0]); ++ mtk_rx_clean(eth, ð->rx_ring_qdma); + + if (eth->hwlro) { + mtk_hwlro_rx_uninit(eth); + for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) +- mtk_rx_clean(eth, i); ++ mtk_rx_clean(eth, ð->rx_ring[i]); + } + + kfree(eth->scratch_head); +@@ -1723,7 +1737,9 @@ static int mtk_start_dma(struct mtk_eth + + mtk_w32(eth, + MTK_TX_WB_DDONE | MTK_TX_DMA_EN | +- MTK_DMA_SIZE_16DWORDS | MTK_NDP_CO_PRO, ++ MTK_DMA_SIZE_16DWORDS | MTK_NDP_CO_PRO | ++ MTK_RX_DMA_EN | MTK_RX_2B_OFFSET | ++ MTK_RX_BT_32DWORDS, + MTK_QDMA_GLO_CFG); + + mtk_w32(eth, +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -484,6 +484,7 @@ struct mtk_tx_ring { + enum mtk_rx_flags { + MTK_RX_FLAGS_NORMAL = 0, + MTK_RX_FLAGS_HWLRO, ++ MTK_RX_FLAGS_QDMA, + }; + + /* struct mtk_rx_ring - This struct holds info describing a RX ring +@@ -527,6 +528,7 @@ struct mtk_rx_ring { + * @dma_refcnt: track how many netdevs are using the DMA engine + * @tx_ring: Pointer to the memory holding info about the TX ring + * @rx_ring: Pointer to the memory holding info about the RX ring ++ * @rx_ring_qdma: Pointer to the memory holding info about the QDMA RX ring + * @tx_napi: The TX NAPI struct + * @rx_napi: The RX NAPI struct + * @scratch_ring: Newer SoCs need memory for a second HW managed TX ring +@@ -556,6 +558,7 @@ struct mtk_eth { + atomic_t dma_refcnt; + struct mtk_tx_ring tx_ring; + struct mtk_rx_ring rx_ring[MTK_MAX_RX_RING_NUM]; ++ struct mtk_rx_ring rx_ring_qdma; + struct napi_struct tx_napi; + struct napi_struct rx_napi; + struct mtk_tx_dma *scratch_ring; diff --git a/target/linux/mediatek/patches-4.9/0038-net-next-dsa-move-struct-dsa_device_ops-to-the-globa.patch b/target/linux/mediatek/patches-4.9/0038-net-next-dsa-move-struct-dsa_device_ops-to-the-globa.patch new file mode 100644 index 0000000..cb1c1b9 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0038-net-next-dsa-move-struct-dsa_device_ops-to-the-globa.patch @@ -0,0 +1,46 @@ +From b58bf0220f666705e63fe8d361f37c913aee2d8f Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Fri, 21 Jul 2017 09:32:54 +0200 +Subject: [PATCH 38/57] net-next: dsa: move struct dsa_device_ops to the global + header file + +We need to access this struct from within the flow_dissector to fix +dissection for packets coming in on DSA devices. + +Signed-off-by: John Crispin <john@phrozen.org> +--- + include/net/dsa.h | 7 +++++++ + net/dsa/dsa_priv.h | 6 ------ + 2 files changed, 7 insertions(+), 6 deletions(-) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -88,6 +88,13 @@ struct dsa_platform_data { + + struct packet_type; + ++struct dsa_device_ops { ++ struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); ++ int sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev, ++ struct packet_type *pt, ++ struct net_device *orig_dev); ++}; ++ + struct dsa_switch_tree { + struct list_head list; + +--- a/net/dsa/dsa_priv.h ++++ b/net/dsa/dsa_priv.h +@@ -15,12 +15,6 @@ + #include <linux/netdevice.h> + #include <linux/netpoll.h> + +-struct dsa_device_ops { +- struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); +- int (*rcv)(struct sk_buff *skb, struct net_device *dev, +- struct packet_type *pt, struct net_device *orig_dev); +-}; +- + struct dsa_slave_priv { + struct sk_buff * (*xmit)(struct sk_buff *skb, + struct net_device *dev); diff --git a/target/linux/mediatek/patches-4.9/0039-net-next-dsa-add-flow_dissect-callback-to-struct-dsa.patch b/target/linux/mediatek/patches-4.9/0039-net-next-dsa-add-flow_dissect-callback-to-struct-dsa.patch new file mode 100644 index 0000000..ebc52c8 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0039-net-next-dsa-add-flow_dissect-callback-to-struct-dsa.patch @@ -0,0 +1,32 @@ +From 22e8b65ea4bf8a1fa757137bdcbdefe505fa4044 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Mon, 7 Aug 2017 16:35:43 +0200 +Subject: [PATCH 39/57] net-next: dsa: add flow_dissect callback to struct + dsa_device_ops + +When the flow dissector first sees packets coming in on a DSA devices the +802.3 header wont be located where the code expects it to be as the tag +is still present. Adding this new callback allows a DSA device to provide a +new function that the flow_disscetor can use to get the correct offsets +for the protocol field and network header offset. + +Signed-off-by: John Crispin <john@phrozen.org> +--- + include/net/dsa.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -90,9 +90,11 @@ struct packet_type; + + struct dsa_device_ops { + struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); +- int sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev, ++ int (*rcv)(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, + struct net_device *orig_dev); ++ int (*flow_dissect)(const struct sk_buff *skb, __be16 *proto, ++ int *offset); + }; + + struct dsa_switch_tree { diff --git a/target/linux/mediatek/patches-4.9/0040-net-next-tag_mtk-add-flow_dissect-callback-to-the-op.patch b/target/linux/mediatek/patches-4.9/0040-net-next-tag_mtk-add-flow_dissect-callback-to-the-op.patch new file mode 100644 index 0000000..da98a21 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0040-net-next-tag_mtk-add-flow_dissect-callback-to-the-op.patch @@ -0,0 +1,39 @@ +From 9d6806e16e5ea68a49225da1ab065ef0b5d7704b Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Mon, 7 Aug 2017 16:55:56 +0200 +Subject: [PATCH 40/57] net-next: tag_mtk: add flow_dissect callback to the ops + struct + +The MT7530 inserts the 4 magic header in between the 802.3 address and +protocol field. The patch implements the callback that can be called by +the flow dissector to figure out the real protocol and offset of the +network header. With this patch applied we can properly parse the packet +and thus make hashing function properly. + +Signed-off-by: John Crispin <john@phrozen.org> +--- + net/dsa/tag_mtk.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/net/dsa/tag_mtk.c ++++ b/net/dsa/tag_mtk.c +@@ -111,7 +111,17 @@ out: + return 0; + } + ++static int mtk_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto, ++ int *offset) ++{ ++ *offset = 4; ++ *proto = ((__be16 *)skb->data)[1]; ++ ++ return 0; ++} ++ + const struct dsa_device_ops mtk_netdev_ops = { +- .xmit = mtk_tag_xmit, +- .rcv = mtk_tag_rcv, ++ .xmit = mtk_tag_xmit, ++ .rcv = mtk_tag_rcv, ++ .flow_dissect = mtk_tag_flow_dissect, + }; diff --git a/target/linux/mediatek/patches-4.9/0041-net-next-dsa-fix-flow-dissection.patch b/target/linux/mediatek/patches-4.9/0041-net-next-dsa-fix-flow-dissection.patch new file mode 100644 index 0000000..5435962 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0041-net-next-dsa-fix-flow-dissection.patch @@ -0,0 +1,65 @@ +From 04c825484d6ecdcc8ce09b350235c9077eaca6e3 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Wed, 9 Aug 2017 08:20:21 +0200 +Subject: [PATCH 41/57] net-next: dsa: fix flow dissection + +RPS and probably other kernel features are currently broken on some if not +all DSA devices. The root cause of this is that skb_hash will call the +flow_dissector. At this point the skb still contains the magic switch +header and the skb->protocol field is not set up to the correct 802.3 +value yet. By the time the tag specific code is called, removing the header +and =roperly setting the protocol an invalid hash is already set. In the +case of the mt7530 this will result in all flows always having the same +hash. + +This patch makes the flow dissector honour the nh and protocol offset +defined by the dsa tag driver thus fixing dissection, hashing and RPS. + +Signed-off-by: John Crispin <john@phrozen.org> +--- + net/core/flow_dissector.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +--- a/net/core/flow_dissector.c ++++ b/net/core/flow_dissector.c +@@ -4,6 +4,7 @@ + #include <linux/ip.h> + #include <linux/ipv6.h> + #include <linux/if_vlan.h> ++#include <net/dsa.h> + #include <net/ip.h> + #include <net/ipv6.h> + #include <net/gre.h> +@@ -123,13 +124,23 @@ bool __skb_flow_dissect(const struct sk_ + bool skip_vlan = false; + u8 ip_proto = 0; + bool ret; +- + if (!data) { + data = skb->data; + proto = skb_vlan_tag_present(skb) ? + skb->vlan_proto : skb->protocol; + nhoff = skb_network_offset(skb); + hlen = skb_headlen(skb); ++ if (unlikely(netdev_uses_dsa(skb->dev))) { ++ const struct dsa_device_ops *ops; ++ int offset; ++ ++ ops = skb->dev->dsa_ptr->tag_ops; ++ if (ops->flow_dissect && ++ !ops->flow_dissect(skb, &proto, &offset)) { ++ hlen -= offset; ++ nhoff += offset; ++ } ++ } + } + + /* It is ensured by skb_flow_dissector_init() that control key will +@@ -162,6 +173,7 @@ again: + case htons(ETH_P_IP): { + const struct iphdr *iph; + struct iphdr _iph; ++ + ip: + iph = __skb_header_pointer(skb, nhoff, sizeof(_iph), data, hlen, &_iph); + if (!iph || iph->ihl < 5) diff --git a/target/linux/mediatek/patches-4.9/0042-net-next-mediatek-honour-special-tag-bit-inside-RX-D.patch b/target/linux/mediatek/patches-4.9/0042-net-next-mediatek-honour-special-tag-bit-inside-RX-D.patch new file mode 100644 index 0000000..4f2c7b2 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0042-net-next-mediatek-honour-special-tag-bit-inside-RX-D.patch @@ -0,0 +1,50 @@ +From a306af3b97c56b9e224a2f9ee04838a2d32ff60b Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Wed, 9 Aug 2017 14:44:07 +0200 +Subject: [PATCH 42/57] net-next: mediatek: honour special tag bit inside RX + DMA descriptor + +For HW NAT/QoS to work the DSA driver needs to turn the special tag bit +inside the ingress control register on. This has the side effect that +the code working out which ingress gmac we have breaks. Fix this by +honouring the special tag bit inside the RX free descriptor. + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 14 ++++++++++---- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + + 2 files changed, 11 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -933,10 +933,16 @@ static int mtk_poll_rx(struct napi_struc + if (!(trxd.rxd2 & RX_DMA_DONE)) + break; + +- /* find out which mac the packet come from. values start at 1 */ +- mac = (trxd.rxd4 >> RX_DMA_FPORT_SHIFT) & +- RX_DMA_FPORT_MASK; +- mac--; ++ /* find out which mac the packet comes from. If the special tag is ++ * we can assume that the traffic is coming from the builtin mt7530 ++ * and the DSA driver has loaded. FPORT will be the physical switch ++ * port in this case rather than the FE forward port id. */ ++ if (!(trxd.rxd4 & RX_DMA_SP_TAG)) { ++ /* values start at 1 */ ++ mac = (trxd.rxd4 >> RX_DMA_FPORT_SHIFT) & ++ RX_DMA_FPORT_MASK; ++ mac--; ++ } + + netdev = eth->netdev[mac]; + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -284,6 +284,7 @@ + + /* QDMA descriptor rxd4 */ + #define RX_DMA_L4_VALID BIT(24) ++#define RX_DMA_SP_TAG BIT(22) + #define RX_DMA_FPORT_SHIFT 19 + #define RX_DMA_FPORT_MASK 0x7 + diff --git a/target/linux/mediatek/patches-4.9/0043-net-next-mediatek-enable-special-tag-indication-for-.patch b/target/linux/mediatek/patches-4.9/0043-net-next-mediatek-enable-special-tag-indication-for-.patch new file mode 100644 index 0000000..2256325 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0043-net-next-mediatek-enable-special-tag-indication-for-.patch @@ -0,0 +1,41 @@ +From 53e3d9af39805a7e1ba81a047a9ab433be0e82f5 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Wed, 9 Aug 2017 14:56:53 +0200 +Subject: [PATCH 43/57] net-next: mediatek: enable special tag indication for + PDMA + +The Ingress special tag indication was only enabled for QDMA and not PDMA. +Properly initialize the STAG bit. This broke HW NAT and Qos from working +for traffic coming in via a DSA device. The PPE failed to properly parse +the traffic as it was not expecting the special tag. + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++ + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++++ + 2 files changed, 6 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1894,6 +1894,8 @@ static int mtk_hw_init(struct mtk_eth *e + */ + val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); + mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); ++ val = mtk_r32(eth, MTK_CDMP_IG_CTRL); ++ mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); + + /* Enable RX VLan Offloading */ + if (MTK_HW_FEATURES & NETIF_F_HW_VLAN_CTAG_RX) +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -76,6 +76,10 @@ + #define MTK_CDMQ_IG_CTRL 0x1400 + #define MTK_CDMQ_STAG_EN BIT(0) + ++/* CDMP Ingress Control Register */ ++#define MTK_CDMP_IG_CTRL 0x400 ++#define MTK_CDMP_STAG_EN BIT(0) ++ + /* CDMP Exgress Control Register */ + #define MTK_CDMP_EG_CTRL 0x404 + diff --git a/target/linux/mediatek/patches-4.9/0044-net-next-dsa-mediatek-tell-GDMA-when-we-are-turning-.patch b/target/linux/mediatek/patches-4.9/0044-net-next-dsa-mediatek-tell-GDMA-when-we-are-turning-.patch new file mode 100644 index 0000000..51204d4 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0044-net-next-dsa-mediatek-tell-GDMA-when-we-are-turning-.patch @@ -0,0 +1,43 @@ +From 6a5932028a4f3217ed7c9d602f269611d95dd8ca Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Wed, 9 Aug 2017 15:13:19 +0200 +Subject: [PATCH 44/57] net-next: dsa: mediatek: tell GDMA when we are turning + on the special tag + +Enabling this bit will make the RX DMA descriptor enable the SP bit for all +ingress traffic inside the return descriptor. The PPE needs this to know +that a SP is present. + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/dsa/mt7530.c | 5 +++++ + drivers/net/dsa/mt7530.h | 4 ++++ + 2 files changed, 9 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -742,6 +742,11 @@ mt7530_cpu_port_enable(struct mt7530_pri + mt7530_write(priv, MT7530_PVC_P(port), + PORT_SPEC_TAG); + ++ /* Enable Mediatek header mode on the GMAC that the cpu port ++ * connects to */ ++ regmap_write_bits(priv->ethernet, MTK_GDMA_FWD_CFG(port), ++ GDMA_SPEC_TAG, GDMA_SPEC_TAG); ++ + /* Setup the MAC by default for the cpu port */ + mt7530_write(priv, MT7530_PMCR_P(port), PMCR_CPUP_LINK); + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -22,6 +22,10 @@ + + #define TRGMII_BASE(x) (0x10000 + (x)) + ++/* Registers for GDMA configuration access */ ++#define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000)) ++#define GDMA_SPEC_TAG BIT(24) ++ + /* Registers to ethsys access */ + #define ETHSYS_CLKCFG0 0x2c + #define ETHSYS_TRGMII_CLK_SEL362_5 BIT(11) diff --git a/target/linux/mediatek/patches-4.9/0045-net-dsa-mediatek-turn-into-platform-driver.patch b/target/linux/mediatek/patches-4.9/0045-net-dsa-mediatek-turn-into-platform-driver.patch new file mode 100644 index 0000000..c263b07 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0045-net-dsa-mediatek-turn-into-platform-driver.patch @@ -0,0 +1,79 @@ +From 1e33784f665cb95c2af5481d3e776d2d3099921b Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 15:57:17 +0200 +Subject: [PATCH 45/57] net: dsa: mediatek: turn into platform driver + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/dsa/mt7530.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1035,10 +1035,10 @@ static struct dsa_switch_ops mt7530_swit + }; + + static int +-mt7530_probe(struct mdio_device *mdiodev) ++mt7530_probe(struct platform_device *mdiodev) + { + struct mt7530_priv *priv; +- struct device_node *dn; ++ struct device_node *dn, *mdio; + + dn = mdiodev->dev.of_node; + +@@ -1086,7 +1086,12 @@ mt7530_probe(struct mdio_device *mdiodev + } + } + +- priv->bus = mdiodev->bus; ++ mdio = of_parse_phandle(dn, "dsa,mii-bus", 0); ++ if (!mdio) ++ return -EINVAL; ++ priv->bus = of_mdio_find_bus(mdio); ++ if (!priv->bus) ++ return -EPROBE_DEFER; + priv->dev = &mdiodev->dev; + priv->ds->priv = priv; + priv->ds->dev = &mdiodev->dev; +@@ -1098,8 +1103,8 @@ mt7530_probe(struct mdio_device *mdiodev + return dsa_register_switch(priv->ds, priv->ds->dev->of_node); + } + +-static void +-mt7530_remove(struct mdio_device *mdiodev) ++static int ++mt7530_remove(struct platform_device *mdiodev) + { + struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); + int ret = 0; +@@ -1116,6 +1121,8 @@ mt7530_remove(struct mdio_device *mdiode + + dsa_unregister_switch(priv->ds); + mutex_destroy(&priv->reg_mutex); ++ ++ return 0; + } + + static const struct of_device_id mt7530_of_match[] = { +@@ -1123,16 +1130,16 @@ static const struct of_device_id mt7530_ + { /* sentinel */ }, + }; + +-static struct mdio_driver mt7530_mdio_driver = { ++static struct platform_driver mtk_mt7530_driver = { + .probe = mt7530_probe, + .remove = mt7530_remove, +- .mdiodrv.driver = { ++ .driver = { + .name = "mt7530", + .of_match_table = mt7530_of_match, + }, + }; ++module_platform_driver(mtk_mt7530_driver); + +-mdio_module_driver(mt7530_mdio_driver); + + MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); + MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch"); diff --git a/target/linux/mediatek/patches-4.9/0046-net-mediatek-add-irq-delay.patch b/target/linux/mediatek/patches-4.9/0046-net-mediatek-add-irq-delay.patch new file mode 100644 index 0000000..47c3980 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0046-net-mediatek-add-irq-delay.patch @@ -0,0 +1,56 @@ +From 6e081074df96bf3762c2e6438c383f11a56b0a7e Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 15:58:04 +0200 +Subject: [PATCH 46/57] net: mediatek: add irq delay + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 ++++++- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 8 +++++++- + 2 files changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1904,8 +1904,13 @@ static int mtk_hw_init(struct mtk_eth *e + mtk_w32(eth, 0, MTK_CDMP_EG_CTRL); + + /* disable delay and normal interrupt */ +- mtk_w32(eth, 0, MTK_QDMA_DELAY_INT); ++#ifdef MTK_IRQ_DLY ++ mtk_w32(eth, 0x84048404, MTK_PDMA_DELAY_INT); ++ mtk_w32(eth, 0x84048404, MTK_QDMA_DELAY_INT); ++#else + mtk_w32(eth, 0, MTK_PDMA_DELAY_INT); ++ mtk_w32(eth, 0, MTK_QDMA_DELAY_INT); ++#endif + mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0); + mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0); + mtk_w32(eth, RST_GL_PSE, MTK_RST_GL); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -12,6 +12,8 @@ + * Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com> + */ + ++#define MTK_IRQ_DLY ++ + #ifndef MTK_ETH_H + #define MTK_ETH_H + +@@ -220,11 +222,15 @@ + #define MTK_TX_DONE_INT2 BIT(2) + #define MTK_TX_DONE_INT1 BIT(1) + #define MTK_TX_DONE_INT0 BIT(0) ++#ifdef MTK_IRQ_DLY ++#define MTK_RX_DONE_INT BIT(30) ++#define MTK_TX_DONE_INT BIT(28) ++#else + #define MTK_RX_DONE_INT (MTK_RX_DONE_INT0 | MTK_RX_DONE_INT1 | \ + MTK_RX_DONE_INT2 | MTK_RX_DONE_INT3) + #define MTK_TX_DONE_INT (MTK_TX_DONE_INT0 | MTK_TX_DONE_INT1 | \ + MTK_TX_DONE_INT2 | MTK_TX_DONE_INT3) +- ++#endif + /* QDMA Interrupt grouping registers */ + #define MTK_QDMA_INT_GRP1 0x1a20 + #define MTK_QDMA_INT_GRP2 0x1a24 diff --git a/target/linux/mediatek/patches-4.9/0047-net-next-mediatek-split-IRQ-register-locking-into-TX.patch b/target/linux/mediatek/patches-4.9/0047-net-next-mediatek-split-IRQ-register-locking-into-TX.patch new file mode 100644 index 0000000..27a78a6 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0047-net-next-mediatek-split-IRQ-register-locking-into-TX.patch @@ -0,0 +1,208 @@ +From 5afceece38fa30e3c71e7ed9ac62aa70ba8cfbb1 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Fri, 16 Jun 2017 10:00:30 +0200 +Subject: [PATCH 47/57] net-next: mediatek: split IRQ register locking into TX + and RX + +Originally the driver only utilized the new QDMA engine. The current code +still assumes this is the case when locking the IRQ mask register. Since +RX now runs on the old style PDMA engine we can add a second lock. This +patch reduces the IRQ latency as the TX and RX path no longer need to wait +on each other under heavy load. + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 79 ++++++++++++++++++----------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 5 +- + 2 files changed, 54 insertions(+), 30 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -372,28 +372,48 @@ static void mtk_mdio_cleanup(struct mtk_ + mdiobus_unregister(eth->mii_bus); + } + +-static inline void mtk_irq_disable(struct mtk_eth *eth, +- unsigned reg, u32 mask) ++static inline void mtk_tx_irq_disable(struct mtk_eth *eth, u32 mask) + { + unsigned long flags; + u32 val; + +- spin_lock_irqsave(ð->irq_lock, flags); +- val = mtk_r32(eth, reg); +- mtk_w32(eth, val & ~mask, reg); +- spin_unlock_irqrestore(ð->irq_lock, flags); ++ spin_lock_irqsave(ð->tx_irq_lock, flags); ++ val = mtk_r32(eth, MTK_QDMA_INT_MASK); ++ mtk_w32(eth, val & ~mask, MTK_QDMA_INT_MASK); ++ spin_unlock_irqrestore(ð->tx_irq_lock, flags); + } + +-static inline void mtk_irq_enable(struct mtk_eth *eth, +- unsigned reg, u32 mask) ++static inline void mtk_tx_irq_enable(struct mtk_eth *eth, u32 mask) + { + unsigned long flags; + u32 val; + +- spin_lock_irqsave(ð->irq_lock, flags); +- val = mtk_r32(eth, reg); +- mtk_w32(eth, val | mask, reg); +- spin_unlock_irqrestore(ð->irq_lock, flags); ++ spin_lock_irqsave(ð->tx_irq_lock, flags); ++ val = mtk_r32(eth, MTK_QDMA_INT_MASK); ++ mtk_w32(eth, val | mask, MTK_QDMA_INT_MASK); ++ spin_unlock_irqrestore(ð->tx_irq_lock, flags); ++} ++ ++static inline void mtk_rx_irq_disable(struct mtk_eth *eth, u32 mask) ++{ ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(ð->rx_irq_lock, flags); ++ val = mtk_r32(eth, MTK_PDMA_INT_MASK); ++ mtk_w32(eth, val & ~mask, MTK_PDMA_INT_MASK); ++ spin_unlock_irqrestore(ð->rx_irq_lock, flags); ++} ++ ++static inline void mtk_rx_irq_enable(struct mtk_eth *eth, u32 mask) ++{ ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(ð->rx_irq_lock, flags); ++ val = mtk_r32(eth, MTK_PDMA_INT_MASK); ++ mtk_w32(eth, val | mask, MTK_PDMA_INT_MASK); ++ spin_unlock_irqrestore(ð->rx_irq_lock, flags); + } + + static int mtk_set_mac_address(struct net_device *dev, void *p) +@@ -1116,7 +1136,7 @@ static int mtk_napi_tx(struct napi_struc + return budget; + + napi_complete(napi); +- mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); ++ mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); + + return tx_done; + } +@@ -1150,7 +1170,7 @@ poll_again: + goto poll_again; + } + napi_complete(napi); +- mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); ++ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); + + return rx_done + budget - remain_budget; + } +@@ -1699,7 +1719,7 @@ static irqreturn_t mtk_handle_irq_rx(int + + if (likely(napi_schedule_prep(ð->rx_napi))) { + __napi_schedule(ð->rx_napi); +- mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); ++ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); + } + + return IRQ_HANDLED; +@@ -1711,7 +1731,7 @@ static irqreturn_t mtk_handle_irq_tx(int + + if (likely(napi_schedule_prep(ð->tx_napi))) { + __napi_schedule(ð->tx_napi); +- mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); ++ mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); + } + + return IRQ_HANDLED; +@@ -1723,11 +1743,11 @@ static void mtk_poll_controller(struct n + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; + +- mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); +- mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); ++ mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); ++ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); + mtk_handle_irq_rx(eth->irq[2], dev); +- mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); +- mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); ++ mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); ++ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); + } + #endif + +@@ -1770,8 +1790,8 @@ static int mtk_open(struct net_device *d + + napi_enable(ð->tx_napi); + napi_enable(ð->rx_napi); +- mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); +- mtk_irq_enable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); ++ mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); ++ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); + } + atomic_inc(ð->dma_refcnt); + +@@ -1816,8 +1836,8 @@ static int mtk_stop(struct net_device *d + if (!atomic_dec_and_test(ð->dma_refcnt)) + return 0; + +- mtk_irq_disable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT); +- mtk_irq_disable(eth, MTK_PDMA_INT_MASK, MTK_RX_DONE_INT); ++ mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); ++ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); + napi_disable(ð->tx_napi); + napi_disable(ð->rx_napi); + +@@ -1911,8 +1931,8 @@ static int mtk_hw_init(struct mtk_eth *e + mtk_w32(eth, 0, MTK_PDMA_DELAY_INT); + mtk_w32(eth, 0, MTK_QDMA_DELAY_INT); + #endif +- mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0); +- mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0); ++ mtk_tx_irq_disable(eth, ~0); ++ mtk_rx_irq_disable(eth, ~0); + mtk_w32(eth, RST_GL_PSE, MTK_RST_GL); + mtk_w32(eth, 0, MTK_RST_GL); + +@@ -1983,8 +2003,8 @@ static void mtk_uninit(struct net_device + phy_disconnect(dev->phydev); + if (of_phy_is_fixed_link(mac->of_node)) + of_phy_deregister_fixed_link(mac->of_node); +- mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0); +- mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0); ++ mtk_tx_irq_disable(eth, ~0); ++ mtk_rx_irq_disable(eth, ~0); + } + + static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +@@ -2442,7 +2462,8 @@ static int mtk_probe(struct platform_dev + return PTR_ERR(eth->base); + + spin_lock_init(ð->page_lock); +- spin_lock_init(ð->irq_lock); ++ spin_lock_init(ð->tx_irq_lock); ++ spin_lock_init(ð->rx_irq_lock); + + eth->ethsys = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "mediatek,ethsys"); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -526,6 +526,8 @@ struct mtk_rx_ring { + * @dev: The device pointer + * @base: The mapped register i/o base + * @page_lock: Make sure that register operations are atomic ++ * @tx_irq__lock: Make sure that IRQ register operations are atomic ++ * @rx_irq__lock: Make sure that IRQ register operations are atomic + * @dummy_dev: we run 2 netdevs on 1 physical DMA ring and need a + * dummy for NAPI to work + * @netdev: The netdev instances +@@ -555,7 +557,8 @@ struct mtk_eth { + struct device *dev; + void __iomem *base; + spinlock_t page_lock; +- spinlock_t irq_lock; ++ spinlock_t tx_irq_lock; ++ spinlock_t rx_irq_lock; + struct net_device dummy_dev; + struct net_device *netdev[MTK_MAX_DEVS]; + struct mtk_mac *mac[MTK_MAX_DEVS]; diff --git a/target/linux/mediatek/patches-4.9/0048-net-core-add-RPS-balancer.patch b/target/linux/mediatek/patches-4.9/0048-net-core-add-RPS-balancer.patch new file mode 100644 index 0000000..20d0e43 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0048-net-core-add-RPS-balancer.patch @@ -0,0 +1,90 @@ +From 3e969c9695b45e1a052d43b367096ec99f2f0aac Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 15:58:29 +0200 +Subject: [PATCH 48/57] net: core: add RPS balancer + +Signed-off-by: John Crispin <john@phrozen.org> +--- + net/core/dev.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 56 insertions(+), 1 deletion(-) + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -3547,6 +3547,58 @@ set_rps_cpu(struct net_device *dev, stru + return rflow; + } + ++#define RPS_TBL_SIZE_SHIFT 10 ++#define RPS_TBL_SIZE (1 << RPS_TBL_SIZE_SHIFT) ++struct rps_table { ++ int core; ++ struct timer_list expire; ++}; ++static struct rps_table rps_table[RPS_TBL_SIZE]; ++static int rps_table_last_core; ++ ++static void rps_table_expire(unsigned long data) ++{ ++ struct rps_table *entry = (struct rps_table *) data; ++ ++ entry->core = -1; ++} ++ ++static int rps_table_core(struct rps_map *map) ++{ ++ int i; ++ ++ for (i = 0; i < map->len; i++) { ++ int cpu = map->cpus[(rps_table_last_core + i + 1) % map->len]; ++ if (cpu_online(cpu)) { ++ rps_table_last_core = cpu; ++ return cpu; ++ } ++ } ++ return map->cpus[0]; ++} ++ ++static int rps_table_lookup(struct rps_map *map, u32 hash) ++{ ++ int bucket = hash & 0x3ff; ++ ++ if (rps_table[bucket].core < 0) ++ rps_table[bucket].core = rps_table_core(map); ++ mod_timer(&rps_table[bucket].expire, jiffies + HZ); ++ ++ return rps_table[bucket].core; ++} ++ ++static void rps_table_init(void) ++{ ++ int i; ++ ++ for (i = 0; i < RPS_TBL_SIZE; i++) { ++ rps_table[i].core = -1; ++ setup_timer(&rps_table[i].expire, rps_table_expire, ++ (unsigned long) &rps_table[i]); ++ } ++} ++ + /* + * get_rps_cpu is called from netif_receive_skb and returns the target + * CPU from the RPS map of the receiving queue for a given skb. +@@ -3636,7 +3688,7 @@ static int get_rps_cpu(struct net_device + try_rps: + + if (map) { +- tcpu = map->cpus[reciprocal_scale(hash, map->len)]; ++ tcpu = rps_table_lookup(map, hash); + if (cpu_online(tcpu)) { + cpu = tcpu; + goto done; +@@ -8426,6 +8478,9 @@ static int __init net_dev_init(void) + sd->backlog.weight = weight_p; + } + ++ if (IS_ENABLED(CONFIG_RPS)) ++ rps_table_init(); ++ + dev_boot_phase = 0; + + /* The loopback device is special if any other network devices diff --git a/target/linux/mediatek/patches-4.9/0049-net-mediatek-add-rx-queue.patch b/target/linux/mediatek/patches-4.9/0049-net-mediatek-add-rx-queue.patch new file mode 100644 index 0000000..0146a9d --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0049-net-mediatek-add-rx-queue.patch @@ -0,0 +1,20 @@ +From 066b30a76a0d13cbd2c0d463f9a1e87efc352679 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 15:58:46 +0200 +Subject: [PATCH 49/57] net: mediatek: add rx queue + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1009,6 +1009,7 @@ static int mtk_poll_rx(struct napi_struc + RX_DMA_VID(trxd.rxd3)) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + RX_DMA_VID(trxd.rxd3)); ++ skb_record_rx_queue(skb, 0); + napi_gro_receive(napi, skb); + + ring->data[idx] = new_data; diff --git a/target/linux/mediatek/patches-4.9/0050-net-mediatek-add-trgmii-clock.patch b/target/linux/mediatek/patches-4.9/0050-net-mediatek-add-trgmii-clock.patch new file mode 100644 index 0000000..3d7df70 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0050-net-mediatek-add-trgmii-clock.patch @@ -0,0 +1,21 @@ +From 67c4af99af02d86b627a8cde2e99cc4c9699d2ce Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 15:59:08 +0200 +Subject: [PATCH 50/57] net: mediatek: add trgmii clock + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1873,6 +1873,8 @@ static int mtk_hw_init(struct mtk_eth *e + pm_runtime_enable(eth->dev); + pm_runtime_get_sync(eth->dev); + ++ clk_set_rate(eth->clks[MTK_CLK_TRGPLL], 250000000); ++ + clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]); + clk_prepare_enable(eth->clks[MTK_CLK_ESW]); + clk_prepare_enable(eth->clks[MTK_CLK_GP1]); diff --git a/target/linux/mediatek/patches-4.9/0051-net-mediatek-increase-tx_timeout.patch b/target/linux/mediatek/patches-4.9/0051-net-mediatek-increase-tx_timeout.patch new file mode 100644 index 0000000..3de3e73 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0051-net-mediatek-increase-tx_timeout.patch @@ -0,0 +1,21 @@ +From 5cbf53c7e5eac5bacc409461888789accdaf8eec Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 16:00:06 +0200 +Subject: [PATCH 51/57] net: mediatek: increase tx_timeout + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2384,7 +2384,7 @@ static int mtk_add_mac(struct mtk_eth *e + mac->hw_stats->reg_offset = id * MTK_STAT_OFFSET; + + SET_NETDEV_DEV(eth->netdev[id], eth->dev); +- eth->netdev[id]->watchdog_timeo = 5 * HZ; ++ eth->netdev[id]->watchdog_timeo = 30 * HZ; + eth->netdev[id]->netdev_ops = &mtk_netdev_ops; + eth->netdev[id]->base_addr = (unsigned long)eth->base; + diff --git a/target/linux/mediatek/patches-4.9/0052-net-phy-add-FC.patch b/target/linux/mediatek/patches-4.9/0052-net-phy-add-FC.patch new file mode 100644 index 0000000..89f730b --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0052-net-phy-add-FC.patch @@ -0,0 +1,21 @@ +From 18b2169d84b47a3414164e5e40f23fb7e875707c Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 16:00:28 +0200 +Subject: [PATCH 52/57] net: phy: add FC + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/phy/phy_device.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1799,7 +1799,7 @@ static struct phy_driver genphy_driver[] + .config_init = genphy_config_init, + .features = PHY_GBIT_FEATURES | SUPPORTED_MII | + SUPPORTED_AUI | SUPPORTED_FIBRE | +- SUPPORTED_BNC, ++ SUPPORTED_BNC | SUPPORTED_Pause | SUPPORTED_Asym_Pause, + .config_aneg = genphy_config_aneg, + .aneg_done = genphy_aneg_done, + .read_status = genphy_read_status, diff --git a/target/linux/mediatek/patches-4.9/0053-net-dsa-mediatek-add-software-phy-polling.patch b/target/linux/mediatek/patches-4.9/0053-net-dsa-mediatek-add-software-phy-polling.patch new file mode 100644 index 0000000..a41bcb0 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0053-net-dsa-mediatek-add-software-phy-polling.patch @@ -0,0 +1,68 @@ +From 53eec2c3580e63fdebfc25ae324f30cd8aa4403b Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 16:00:46 +0200 +Subject: [PATCH 53/57] net: dsa: mediatek: add software phy polling + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/dsa/mt7530.c | 38 ++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/mt7530.h | 1 + + 2 files changed, 39 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -728,6 +728,44 @@ static void mt7530_adjust_link(struct ds + * all finished. + */ + mt7623_pad_clk_setup(ds); ++ } else { ++ u16 lcl_adv = 0, rmt_adv = 0; ++ u8 flowctrl; ++ u32 mcr = PMCR_USERP_LINK | PMCR_FORCE_MODE; ++ ++ switch (phydev->speed) { ++ case SPEED_1000: ++ mcr |= PMCR_FORCE_SPEED_1000; ++ break; ++ case SPEED_100: ++ mcr |= PMCR_FORCE_SPEED_100; ++ break; ++ }; ++ ++ if (phydev->link) ++ mcr |= PMCR_FORCE_LNK; ++ ++ if (phydev->duplex) { ++ mcr |= PMCR_FORCE_FDX; ++ ++ if (phydev->pause) ++ rmt_adv = LPA_PAUSE_CAP; ++ if (phydev->asym_pause) ++ rmt_adv |= LPA_PAUSE_ASYM; ++ ++ if (phydev->advertising & ADVERTISED_Pause) ++ lcl_adv |= ADVERTISE_PAUSE_CAP; ++ if (phydev->advertising & ADVERTISED_Asym_Pause) ++ lcl_adv |= ADVERTISE_PAUSE_ASYM; ++ ++ flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); ++ ++ if (flowctrl & FLOW_CTRL_TX) ++ mcr |= PMCR_TX_FC_EN; ++ if (flowctrl & FLOW_CTRL_RX) ++ mcr |= PMCR_RX_FC_EN; ++ } ++ mt7530_write(priv, MT7530_PMCR_P(port), mcr); + } + } + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -155,6 +155,7 @@ enum mt7530_stp_state { + #define PMCR_TX_FC_EN BIT(5) + #define PMCR_RX_FC_EN BIT(4) + #define PMCR_FORCE_SPEED_1000 BIT(3) ++#define PMCR_FORCE_SPEED_100 BIT(2) + #define PMCR_FORCE_FDX BIT(1) + #define PMCR_FORCE_LNK BIT(0) + #define PMCR_COMMON_LINK (PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \ diff --git a/target/linux/mediatek/patches-4.9/0054-net-ethernet-mediatek-fixed-deadlock-captured-by-loc.patch b/target/linux/mediatek/patches-4.9/0054-net-ethernet-mediatek-fixed-deadlock-captured-by-loc.patch new file mode 100644 index 0000000..2900531 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0054-net-ethernet-mediatek-fixed-deadlock-captured-by-loc.patch @@ -0,0 +1,105 @@ +From 746bf1c3e561aba396cd40e6540245646461117d Mon Sep 17 00:00:00 2001 +From: Sean Wang <sean.wang@mediatek.com> +Date: Tue, 4 Jul 2017 11:17:36 +0800 +Subject: [PATCH 54/57] net: ethernet: mediatek: fixed deadlock captured by + lockdep + +Lockdep found an inconsistent lock state when mtk_get_stats64 is called +in user context while NAPI updates MAC statistics in softirq. + +Use spin_trylock_bh/spin_unlock_bh fix following lockdep warning. + +[ 81.321030] WARNING: inconsistent lock state +[ 81.325266] 4.12.0-rc1-00035-gd9dda65 #32 Not tainted +[ 81.330273] -------------------------------- +[ 81.334505] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. +[ 81.340464] ksoftirqd/0/7 [HC0[0]:SC1[1]:HE1:SE0] takes: +[ 81.345731] (&syncp->seq#2){+.?...}, at: [<c054ba3c>] mtk_handle_status_irq.part.6+0x70/0x84 +[ 81.354219] {SOFTIRQ-ON-W} state was registered at: +[ 81.359062] lock_acquire+0xfc/0x2b0 +[ 81.362696] mtk_stats_update_mac+0x60/0x2c0 +[ 81.367017] mtk_get_stats64+0x17c/0x18c +[ 81.370995] dev_get_stats+0x48/0xbc +[ 81.374628] rtnl_fill_stats+0x48/0x128 +[ 81.378520] rtnl_fill_ifinfo+0x4ac/0xd1c +[ 81.382584] rtmsg_ifinfo_build_skb+0x7c/0xe0 +[ 81.386991] rtmsg_ifinfo.part.5+0x24/0x54 +[ 81.391139] rtmsg_ifinfo+0x24/0x28 +[ 81.394685] __dev_notify_flags+0xa4/0xac +[ 81.398749] dev_change_flags+0x50/0x58 +[ 81.402640] devinet_ioctl+0x768/0x85c +[ 81.406444] inet_ioctl+0x1a4/0x1d0 +[ 81.409990] sock_ioctl+0x16c/0x33c +[ 81.413538] do_vfs_ioctl+0xb4/0xa34 +[ 81.417169] SyS_ioctl+0x44/0x6c +[ 81.420458] ret_fast_syscall+0x0/0x1c +[ 81.424260] irq event stamp: 3354692 +[ 81.427806] hardirqs last enabled at (3354692): [<c0678168>] net_rx_action+0xc0/0x504 +[ 81.435660] hardirqs last disabled at (3354691): [<c0678134>] net_rx_action+0x8c/0x504 +[ 81.443515] softirqs last enabled at (3354106): [<c0101944>] __do_softirq+0x4b4/0x614 +[ 81.451370] softirqs last disabled at (3354109): [<c012f0c4>] run_ksoftirqd+0x44/0x80 +[ 81.459134] +[ 81.459134] other info that might help us debug this: +[ 81.465608] Possible unsafe locking scenario: +[ 81.465608] +[ 81.471478] CPU0 +[ 81.473900] ---- +[ 81.476321] lock(&syncp->seq#2); +[ 81.479701] <Interrupt> +[ 81.482294] lock(&syncp->seq#2); +[ 81.485847] +[ 81.485847] *** DEADLOCK *** +[ 81.485847] +[ 81.491720] 1 lock held by ksoftirqd/0/7: +[ 81.495693] #0: (&(&mac->hw_stats->stats_lock)->rlock){+.+...}, at: [<c054ba14>] mtk_handle_status_irq.part.6+0x48/0x84 +[ 81.506579] +[ 81.506579] stack backtrace: +[ 81.510904] CPU: 0 PID: 7 Comm: ksoftirqd/0 Not tainted 4.12.0-rc1-00035-gd9dda65 #32 +[ 81.518668] Hardware name: Mediatek Cortex-A7 (Device Tree) +[ 81.524208] [<c0113dc4>] (unwind_backtrace) from [<c010e3f0>] (show_stack+0x20/0x24) +[ 81.531899] [<c010e3f0>] (show_stack) from [<c03f9c64>] (dump_stack+0xb4/0xe0) +[ 81.539072] [<c03f9c64>] (dump_stack) from [<c017e970>] (print_usage_bug+0x234/0x2e0) +[ 81.546846] [<c017e970>] (print_usage_bug) from [<c017f058>] (mark_lock+0x63c/0x7bc) +[ 81.554532] [<c017f058>] (mark_lock) from [<c017fe90>] (__lock_acquire+0x654/0x1bfc) +[ 81.562217] [<c017fe90>] (__lock_acquire) from [<c0181d04>] (lock_acquire+0xfc/0x2b0) +[ 81.569990] [<c0181d04>] (lock_acquire) from [<c054b76c>] (mtk_stats_update_mac+0x60/0x2c0) +[ 81.578283] [<c054b76c>] (mtk_stats_update_mac) from [<c054ba3c>] (mtk_handle_status_irq.part.6+0x70/0x84) +[ 81.587865] [<c054ba3c>] (mtk_handle_status_irq.part.6) from [<c054c2b8>] (mtk_napi_tx+0x358/0x37c) +[ 81.596845] [<c054c2b8>] (mtk_napi_tx) from [<c06782ec>] (net_rx_action+0x244/0x504) +[ 81.604533] [<c06782ec>] (net_rx_action) from [<c01015c4>] (__do_softirq+0x134/0x614) +[ 81.612306] [<c01015c4>] (__do_softirq) from [<c012f0c4>] (run_ksoftirqd+0x44/0x80) +[ 81.619907] [<c012f0c4>] (run_ksoftirqd) from [<c0154680>] (smpboot_thread_fn+0x14c/0x25c) +[ 81.628110] [<c0154680>] (smpboot_thread_fn) from [<c014f8cc>] (kthread+0x150/0x180) +[ 81.635798] [<c014f8cc>] (kthread) from [<c0109290>] (ret_from_fork+0x14/0x24) + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -493,9 +493,9 @@ static struct rtnl_link_stats64 * mtk_ge + unsigned int start; + + if (netif_running(dev) && netif_device_present(dev)) { +- if (spin_trylock(&hw_stats->stats_lock)) { ++ if (spin_trylock_bh(&hw_stats->stats_lock)) { + mtk_stats_update_mac(mac); +- spin_unlock(&hw_stats->stats_lock); ++ spin_unlock_bh(&hw_stats->stats_lock); + } + } + +@@ -2229,9 +2229,9 @@ static void mtk_get_ethtool_stats(struct + return; + + if (netif_running(dev) && netif_device_present(dev)) { +- if (spin_trylock(&hwstats->stats_lock)) { ++ if (spin_trylock_bh(&hwstats->stats_lock)) { + mtk_stats_update_mac(mac); +- spin_unlock(&hwstats->stats_lock); ++ spin_unlock_bh(&hwstats->stats_lock); + } + } + diff --git a/target/linux/mediatek/patches-4.9/0055-net-ethernet-mediatek-avoid-potential-invalid-memory.patch b/target/linux/mediatek/patches-4.9/0055-net-ethernet-mediatek-avoid-potential-invalid-memory.patch new file mode 100644 index 0000000..6598e82 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0055-net-ethernet-mediatek-avoid-potential-invalid-memory.patch @@ -0,0 +1,31 @@ +From a3360b3543b9fb833ba691019e396e72293a313f Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 16:31:45 +0200 +Subject: [PATCH 55/57] net: ethernet: mediatek: avoid potential invalid memory + access + +Potential dangerous invalid memory might be accessed if invalid mac value +reflected from the forward port field in rxd4 caused by possible potential +hardware defects. So added a simple sanity checker to avoid the kind of +situation happening. + +Signed-off-by: Sean Wang <sean.wang@mediatek.com> +Acked-by: John Crispin <john@phrozen.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -964,6 +964,10 @@ static int mtk_poll_rx(struct napi_struc + mac--; + } + ++ if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT || ++ !eth->netdev[mac])) ++ goto release_desc; ++ + netdev = eth->netdev[mac]; + + if (unlikely(test_bit(MTK_RESETTING, ð->state))) diff --git a/target/linux/mediatek/patches-4.9/0056-net-mediatek-add-hw-nat-support.patch b/target/linux/mediatek/patches-4.9/0056-net-mediatek-add-hw-nat-support.patch new file mode 100644 index 0000000..d1d6ed4 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0056-net-mediatek-add-hw-nat-support.patch @@ -0,0 +1,119 @@ +From 043efc0e619e04661be2b1889382db2fdd378145 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 16:34:36 +0200 +Subject: [PATCH 56/57] net: mediatek: add hw nat support + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/Kconfig | 7 +++++++ + drivers/net/ethernet/mediatek/Makefile | 1 + + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 13 +++++++++++++ + net/netfilter/nf_conntrack_proto_tcp.c | 19 +++++++++++++++++++ + 4 files changed, 40 insertions(+) + +--- a/drivers/net/ethernet/mediatek/Kconfig ++++ b/drivers/net/ethernet/mediatek/Kconfig +@@ -14,4 +14,11 @@ config NET_MEDIATEK_SOC + This driver supports the gigabit ethernet MACs in the + MediaTek MT2701/MT7623 chipset family. + ++config NET_MEDIATEK_HNAT ++ tristate "MediaTek MT7623 hardware NAT support" ++ depends on NET_MEDIATEK_SOC && NF_CONNTRACK && NF_CONNTRACK_IPV4 && IP_NF_NAT && IP_NF_TARGET_MASQUERADE ++ ---help--- ++ This driver supports the hardwaer NAT in the ++ MediaTek MT2701/MT7623 chipset family. ++ + endif #NET_VENDOR_MEDIATEK +--- a/drivers/net/ethernet/mediatek/Makefile ++++ b/drivers/net/ethernet/mediatek/Makefile +@@ -3,3 +3,4 @@ + # + + obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth_soc.o ++obj-$(CONFIG_NET_MEDIATEK_HNAT) += mtk_hnat/ +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -23,6 +23,10 @@ + #include <linux/reset.h> + #include <linux/tcp.h> + ++#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE) ++#include "mtk_hnat/nf_hnat_mtk.h" ++#endif ++ + #include "mtk_eth_soc.h" + + static int mtk_msg_level = -1; +@@ -649,6 +653,11 @@ static int mtk_tx_map(struct sk_buff *sk + return -ENOMEM; + + /* set the forward port */ ++#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE) ++ if (HNAT_SKB_CB2(skb)->magic == 0x78681415) ++ fport |= 0x4 << TX_DMA_FPORT_SHIFT; ++ else ++#endif + fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT; + txd4 |= fport; + +@@ -1013,6 +1022,10 @@ static int mtk_poll_rx(struct napi_struc + RX_DMA_VID(trxd.rxd3)) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + RX_DMA_VID(trxd.rxd3)); ++#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE) ++ *(u32 *)(skb->head) = trxd.rxd4; ++ skb_hnat_alg(skb) = 0; ++#endif + skb_record_rx_queue(skb, 0); + napi_gro_receive(napi, skb); + +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -11,6 +11,7 @@ + #include <linux/types.h> + #include <linux/timer.h> + #include <linux/module.h> ++#include <linux/inetdevice.h> + #include <linux/in.h> + #include <linux/tcp.h> + #include <linux/spinlock.h> +@@ -19,6 +20,7 @@ + #include <net/ip6_checksum.h> + #include <asm/unaligned.h> + ++#include <net/ip.h> + #include <net/tcp.h> + + #include <linux/netfilter.h> +@@ -53,6 +55,11 @@ static int nf_ct_tcp_max_retrans __read_ + /* FIXME: Examine ipfilter's timeouts and conntrack transitions more + closely. They're more complex. --RR */ + ++#ifndef IPV4_DEVCONF_DFLT ++ #define IPV4_DEVCONF_DFLT(net, attr) \ ++ IPV4_DEVCONF((*net->ipv4.devconf_dflt), attr) ++#endif ++ + static const char *const tcp_conntrack_names[] = { + "NONE", + "SYN_SENT", +@@ -519,6 +526,18 @@ static bool tcp_in_window(const struct n + if (nf_ct_tcp_no_window_check) + return true; + ++ if (net) { ++ if ((net->ipv4.devconf_all && net->ipv4.devconf_dflt && net->ipv6.devconf_all) && ++ net->ipv6.devconf_dflt) { ++ if ((IPV4_DEVCONF_DFLT(net, FORWARDING) || ++ IPV4_DEVCONF_ALL(net, FORWARDING)) || ++ (net->ipv6.devconf_all->forwarding || ++ net->ipv6.devconf_dflt->forwarding)) { ++ return true; ++ } ++ } ++ } ++ + /* + * Get the required data from the packet. + */ diff --git a/target/linux/mediatek/patches-4.9/0057-net-mediatek-add-HW-QoS-support.patch b/target/linux/mediatek/patches-4.9/0057-net-mediatek-add-HW-QoS-support.patch new file mode 100644 index 0000000..f628458 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0057-net-mediatek-add-HW-QoS-support.patch @@ -0,0 +1,121 @@ +From 660c13dfbacbf37f090a66a2b14f0c5ce7cbec81 Mon Sep 17 00:00:00 2001 +From: John Crispin <john@phrozen.org> +Date: Thu, 10 Aug 2017 16:38:27 +0200 +Subject: [PATCH 57/57] net: mediatek: add HW QoS support + +Signed-off-by: John Crispin <john@phrozen.org> +--- + drivers/net/ethernet/mediatek/Kconfig | 7 ++++ + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 60 ++++++++++++++++++++++++++++- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- + 3 files changed, 66 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/mediatek/Kconfig ++++ b/drivers/net/ethernet/mediatek/Kconfig +@@ -21,4 +21,11 @@ config NET_MEDIATEK_HNAT + This driver supports the hardwaer NAT in the + MediaTek MT2701/MT7623 chipset family. + ++config NET_MEDIATEK_HW_QOS ++ tristate "MediaTek MT7623 hardware QoS support" ++ depends on NET_MEDIATEK_SOC ++ ---help--- ++ This driver supports the hardware QoS in the ++ MediaTek MT2701/MT7623 chipset family. ++ + endif #NET_VENDOR_MEDIATEK +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -23,6 +23,17 @@ + #include <linux/reset.h> + #include <linux/tcp.h> + ++#if defined(CONFIG_NET_MEDIATEK_HW_QOS) ++struct mtk_ioctl_reg { ++ unsigned int off; ++ unsigned int val; ++}; ++ ++#define REG_HQOS_MAX 0x3FFF ++#define RAETH_QDMA_REG_READ 0x89F8 ++#define RAETH_QDMA_REG_WRITE 0x89F9 ++#endif ++ + #if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE) + #include "mtk_hnat/nf_hnat_mtk.h" + #endif +@@ -646,7 +657,7 @@ static int mtk_tx_map(struct sk_buff *sk + dma_addr_t mapped_addr; + unsigned int nr_frags; + int i, n_desc = 1; +- u32 txd4 = 0, fport; ++ u32 txd3 = 0, txd4 = 0, fport; + + itxd = ring->next_free; + if (itxd == ring->last_free) +@@ -675,6 +686,12 @@ static int mtk_tx_map(struct sk_buff *sk + // if (skb_vlan_tag_present(skb)) + // txd4 |= TX_DMA_INS_VLAN | skb_vlan_tag_get(skb); + ++#ifdef CONFIG_NET_MEDIATEK_HW_QOS ++ txd3 |= skb->mark & 0x7; ++ if (mac->id) ++ txd3 += 8; ++#endif ++ + mapped_addr = dma_map_single(eth->dev, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(eth->dev, mapped_addr))) +@@ -718,7 +735,8 @@ static int mtk_tx_map(struct sk_buff *sk + WRITE_ONCE(txd->txd1, mapped_addr); + WRITE_ONCE(txd->txd3, (TX_DMA_SWC | + TX_DMA_PLEN0(frag_map_size) | +- last_frag * TX_DMA_LS0)); ++ last_frag * TX_DMA_LS0 | ++ txd3)); + WRITE_ONCE(txd->txd4, fport); + + tx_buf = mtk_desc_to_tx_buf(ring, txd); +@@ -2029,7 +2047,31 @@ static void mtk_uninit(struct net_device + + static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) + { ++#if defined(CONFIG_NET_MEDIATEK_HW_QOS) ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ struct mtk_ioctl_reg reg; ++#endif ++ + switch (cmd) { ++#if defined(CONFIG_NET_MEDIATEK_HW_QOS) ++ case RAETH_QDMA_REG_READ: ++ copy_from_user(®, ifr->ifr_data, sizeof(reg)); ++ if (reg.off > REG_HQOS_MAX) ++ return -EINVAL; ++ reg.val = mtk_r32(eth, 0x1800 + reg.off); ++// printk("read reg off:%x val:%x\n", reg.off, reg.val); ++ copy_to_user(ifr->ifr_data, ®, sizeof(reg)); ++ return 0; ++ ++ case RAETH_QDMA_REG_WRITE: ++ copy_from_user(®, ifr->ifr_data, sizeof(reg)); ++ if (reg.off > REG_HQOS_MAX) ++ return -EINVAL; ++ mtk_w32(eth, reg.val, 0x1800 + reg.off); ++// printk("write reg off:%x val:%x\n", reg.off, reg.val); ++ return 0; ++#endif + case SIOCGMIIPHY: + case SIOCGMIIREG: + case SIOCSMIIREG: +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -20,7 +20,7 @@ + #define MTK_QDMA_PAGE_SIZE 2048 + #define MTK_MAX_RX_LENGTH 1536 + #define MTK_TX_DMA_BUF_LEN 0x3fff +-#define MTK_DMA_SIZE 256 ++#define MTK_DMA_SIZE 2048 + #define MTK_NAPI_WEIGHT 64 + #define MTK_MAC_COUNT 2 + #define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN) diff --git a/target/linux/mediatek/patches-4.9/0058-pinctrl-update.patch b/target/linux/mediatek/patches-4.9/0058-pinctrl-update.patch new file mode 100644 index 0000000..3174b80 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0058-pinctrl-update.patch @@ -0,0 +1,470 @@ +--- a/drivers/pinctrl/mediatek/Kconfig ++++ b/drivers/pinctrl/mediatek/Kconfig +@@ -15,12 +15,6 @@ config PINCTRL_MT2701 + default MACH_MT2701 + select PINCTRL_MTK + +-config PINCTRL_MT7623 +- bool "Mediatek MT7623 pin control" if COMPILE_TEST && !MACH_MT7623 +- depends on OF +- default MACH_MT7623 +- select PINCTRL_MTK_COMMON +- + config PINCTRL_MT8135 + bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135 + depends on OF +--- a/drivers/pinctrl/mediatek/Makefile ++++ b/drivers/pinctrl/mediatek/Makefile +@@ -3,7 +3,6 @@ obj-y += pinctrl-mtk-common.o + + # SoC Drivers + obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o +-obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o + obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o + obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o + obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o +--- a/drivers/pinctrl/mediatek/pinctrl-mt2701.c ++++ b/drivers/pinctrl/mediatek/pinctrl-mt2701.c +@@ -565,6 +565,7 @@ static int mt2701_pinctrl_probe(struct p + + static const struct of_device_id mt2701_pctrl_match[] = { + { .compatible = "mediatek,mt2701-pinctrl", }, ++ { .compatible = "mediatek,mt7623-pinctrl", }, + {} + }; + MODULE_DEVICE_TABLE(of, mt2701_pctrl_match); +--- a/drivers/pinctrl/mediatek/pinctrl-mt7623.c ++++ /dev/null +@@ -1,379 +0,0 @@ +-/* +- * Copyright (c) 2016 John Crispin <blogic@openwrt.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. +- * +- * 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 <dt-bindings/pinctrl/mt65xx.h> +-#include <linux/module.h> +-#include <linux/of.h> +-#include <linux/of_device.h> +-#include <linux/platform_device.h> +-#include <linux/pinctrl/pinctrl.h> +-#include <linux/regmap.h> +- +-#include "pinctrl-mtk-common.h" +-#include "pinctrl-mtk-mt7623.h" +- +-static const struct mtk_drv_group_desc mt7623_drv_grp[] = { +- /* 0E4E8SR 4/8/12/16 */ +- MTK_DRV_GRP(4, 16, 1, 2, 4), +- /* 0E2E4SR 2/4/6/8 */ +- MTK_DRV_GRP(2, 8, 1, 2, 2), +- /* E8E4E2 2/4/6/8/10/12/14/16 */ +- MTK_DRV_GRP(2, 16, 0, 2, 2) +-}; +- +-#define DRV_SEL0 0xf50 +-#define DRV_SEL1 0xf60 +-#define DRV_SEL2 0xf70 +-#define DRV_SEL3 0xf80 +-#define DRV_SEL4 0xf90 +-#define DRV_SEL5 0xfa0 +-#define DRV_SEL6 0xfb0 +-#define DRV_SEL7 0xfe0 +-#define DRV_SEL8 0xfd0 +-#define DRV_SEL9 0xff0 +-#define DRV_SEL10 0xf00 +- +-#define MSDC0_CTRL0 0xcc0 +-#define MSDC0_CTRL1 0xcd0 +-#define MSDC0_CTRL2 0xce0 +-#define MSDC0_CTRL3 0xcf0 +-#define MSDC0_CTRL4 0xd00 +-#define MSDC0_CTRL5 0xd10 +-#define MSDC0_CTRL6 0xd20 +-#define MSDC1_CTRL0 0xd30 +-#define MSDC1_CTRL1 0xd40 +-#define MSDC1_CTRL2 0xd50 +-#define MSDC1_CTRL3 0xd60 +-#define MSDC1_CTRL4 0xd70 +-#define MSDC1_CTRL5 0xd80 +-#define MSDC1_CTRL6 0xd90 +- +-#define IES_EN0 0xb20 +-#define IES_EN1 0xb30 +-#define IES_EN2 0xb40 +- +-#define SMT_EN0 0xb50 +-#define SMT_EN1 0xb60 +-#define SMT_EN2 0xb70 +- +-static const struct mtk_pin_drv_grp mt7623_pin_drv[] = { +- MTK_PIN_DRV_GRP(0, DRV_SEL0, 0, 1), +- MTK_PIN_DRV_GRP(1, DRV_SEL0, 0, 1), +- MTK_PIN_DRV_GRP(2, DRV_SEL0, 0, 1), +- MTK_PIN_DRV_GRP(3, DRV_SEL0, 0, 1), +- MTK_PIN_DRV_GRP(4, DRV_SEL0, 0, 1), +- MTK_PIN_DRV_GRP(5, DRV_SEL0, 0, 1), +- MTK_PIN_DRV_GRP(6, DRV_SEL0, 0, 1), +- MTK_PIN_DRV_GRP(7, DRV_SEL0, 4, 1), +- MTK_PIN_DRV_GRP(8, DRV_SEL0, 4, 1), +- MTK_PIN_DRV_GRP(9, DRV_SEL0, 4, 1), +- MTK_PIN_DRV_GRP(10, DRV_SEL0, 8, 1), +- MTK_PIN_DRV_GRP(11, DRV_SEL0, 8, 1), +- MTK_PIN_DRV_GRP(12, DRV_SEL0, 8, 1), +- MTK_PIN_DRV_GRP(13, DRV_SEL0, 8, 1), +- MTK_PIN_DRV_GRP(14, DRV_SEL0, 12, 0), +- MTK_PIN_DRV_GRP(15, DRV_SEL0, 12, 0), +- MTK_PIN_DRV_GRP(18, DRV_SEL1, 4, 0), +- MTK_PIN_DRV_GRP(19, DRV_SEL1, 4, 0), +- MTK_PIN_DRV_GRP(20, DRV_SEL1, 4, 0), +- MTK_PIN_DRV_GRP(21, DRV_SEL1, 4, 0), +- MTK_PIN_DRV_GRP(22, DRV_SEL1, 8, 0), +- MTK_PIN_DRV_GRP(23, DRV_SEL1, 8, 0), +- MTK_PIN_DRV_GRP(24, DRV_SEL1, 8, 0), +- MTK_PIN_DRV_GRP(25, DRV_SEL1, 8, 0), +- MTK_PIN_DRV_GRP(26, DRV_SEL1, 8, 0), +- MTK_PIN_DRV_GRP(27, DRV_SEL1, 12, 0), +- MTK_PIN_DRV_GRP(28, DRV_SEL1, 12, 0), +- MTK_PIN_DRV_GRP(29, DRV_SEL1, 12, 0), +- MTK_PIN_DRV_GRP(33, DRV_SEL2, 0, 0), +- MTK_PIN_DRV_GRP(34, DRV_SEL2, 0, 0), +- MTK_PIN_DRV_GRP(35, DRV_SEL2, 0, 0), +- MTK_PIN_DRV_GRP(36, DRV_SEL2, 0, 0), +- MTK_PIN_DRV_GRP(37, DRV_SEL2, 0, 0), +- MTK_PIN_DRV_GRP(39, DRV_SEL2, 8, 1), +- MTK_PIN_DRV_GRP(40, DRV_SEL2, 8, 1), +- MTK_PIN_DRV_GRP(41, DRV_SEL2, 8, 1), +- MTK_PIN_DRV_GRP(42, DRV_SEL2, 8, 1), +- MTK_PIN_DRV_GRP(43, DRV_SEL2, 12, 0), +- MTK_PIN_DRV_GRP(44, DRV_SEL2, 12, 0), +- MTK_PIN_DRV_GRP(45, DRV_SEL2, 12, 0), +- MTK_PIN_DRV_GRP(47, DRV_SEL3, 0, 0), +- MTK_PIN_DRV_GRP(48, DRV_SEL3, 0, 0), +- MTK_PIN_DRV_GRP(49, DRV_SEL3, 4, 0), +- MTK_PIN_DRV_GRP(53, DRV_SEL3, 12, 0), +- MTK_PIN_DRV_GRP(54, DRV_SEL3, 12, 0), +- MTK_PIN_DRV_GRP(55, DRV_SEL3, 12, 0), +- MTK_PIN_DRV_GRP(56, DRV_SEL3, 12, 0), +- MTK_PIN_DRV_GRP(60, DRV_SEL4, 8, 1), +- MTK_PIN_DRV_GRP(61, DRV_SEL4, 8, 1), +- MTK_PIN_DRV_GRP(62, DRV_SEL4, 8, 1), +- MTK_PIN_DRV_GRP(63, DRV_SEL4, 12, 1), +- MTK_PIN_DRV_GRP(64, DRV_SEL4, 12, 1), +- MTK_PIN_DRV_GRP(65, DRV_SEL4, 12, 1), +- MTK_PIN_DRV_GRP(66, DRV_SEL5, 0, 1), +- MTK_PIN_DRV_GRP(67, DRV_SEL5, 0, 1), +- MTK_PIN_DRV_GRP(68, DRV_SEL5, 0, 1), +- MTK_PIN_DRV_GRP(69, DRV_SEL5, 0, 1), +- MTK_PIN_DRV_GRP(70, DRV_SEL5, 0, 1), +- MTK_PIN_DRV_GRP(71, DRV_SEL5, 0, 1), +- MTK_PIN_DRV_GRP(72, DRV_SEL3, 4, 0), +- MTK_PIN_DRV_GRP(73, DRV_SEL3, 4, 0), +- MTK_PIN_DRV_GRP(74, DRV_SEL3, 4, 0), +- MTK_PIN_DRV_GRP(83, DRV_SEL5, 0, 1), +- MTK_PIN_DRV_GRP(84, DRV_SEL5, 0, 1), +- MTK_PIN_DRV_GRP(105, MSDC1_CTRL1, 0, 1), +- MTK_PIN_DRV_GRP(106, MSDC1_CTRL0, 0, 1), +- MTK_PIN_DRV_GRP(107, MSDC1_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(108, MSDC1_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(109, MSDC1_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(110, MSDC1_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(111, MSDC0_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(112, MSDC0_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(113, MSDC0_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(114, MSDC0_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(115, MSDC0_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(116, MSDC0_CTRL1, 0, 1), +- MTK_PIN_DRV_GRP(117, MSDC0_CTRL0, 0, 1), +- MTK_PIN_DRV_GRP(118, MSDC0_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(119, MSDC0_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(120, MSDC0_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(121, MSDC0_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(126, DRV_SEL3, 4, 0), +- MTK_PIN_DRV_GRP(199, DRV_SEL0, 4, 1), +- MTK_PIN_DRV_GRP(200, DRV_SEL8, 0, 0), +- MTK_PIN_DRV_GRP(201, DRV_SEL8, 0, 0), +- MTK_PIN_DRV_GRP(203, DRV_SEL8, 4, 0), +- MTK_PIN_DRV_GRP(204, DRV_SEL8, 4, 0), +- MTK_PIN_DRV_GRP(205, DRV_SEL8, 4, 0), +- MTK_PIN_DRV_GRP(206, DRV_SEL8, 4, 0), +- MTK_PIN_DRV_GRP(207, DRV_SEL8, 4, 0), +- MTK_PIN_DRV_GRP(208, DRV_SEL8, 8, 0), +- MTK_PIN_DRV_GRP(209, DRV_SEL8, 8, 0), +- MTK_PIN_DRV_GRP(236, DRV_SEL9, 4, 0), +- MTK_PIN_DRV_GRP(237, DRV_SEL9, 4, 0), +- MTK_PIN_DRV_GRP(238, DRV_SEL9, 4, 0), +- MTK_PIN_DRV_GRP(239, DRV_SEL9, 4, 0), +- MTK_PIN_DRV_GRP(240, DRV_SEL9, 4, 0), +- MTK_PIN_DRV_GRP(241, DRV_SEL9, 4, 0), +- MTK_PIN_DRV_GRP(242, DRV_SEL9, 8, 0), +- MTK_PIN_DRV_GRP(243, DRV_SEL9, 8, 0), +- MTK_PIN_DRV_GRP(257, MSDC0_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(261, MSDC1_CTRL2, 0, 1), +- MTK_PIN_DRV_GRP(262, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(263, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(264, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(265, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(266, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(267, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(268, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(269, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(270, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(271, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(272, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(274, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(275, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(276, DRV_SEL10, 8, 0), +- MTK_PIN_DRV_GRP(278, DRV_SEL2, 8, 1), +-}; +- +-static const struct mtk_pin_spec_pupd_set_samereg mt7623_spec_pupd[] = { +- MTK_PIN_PUPD_SPEC_SR(105, MSDC1_CTRL1, 8, 9, 10), +- MTK_PIN_PUPD_SPEC_SR(106, MSDC1_CTRL0, 8, 9, 10), +- MTK_PIN_PUPD_SPEC_SR(107, MSDC1_CTRL3, 0, 1, 2), +- MTK_PIN_PUPD_SPEC_SR(108, MSDC1_CTRL3, 4, 5, 6), +- MTK_PIN_PUPD_SPEC_SR(109, MSDC1_CTRL3, 8, 9, 10), +- MTK_PIN_PUPD_SPEC_SR(110, MSDC1_CTRL3, 12, 13, 14), +- MTK_PIN_PUPD_SPEC_SR(111, MSDC0_CTRL4, 12, 13, 14), +- MTK_PIN_PUPD_SPEC_SR(112, MSDC0_CTRL4, 8, 9, 10), +- MTK_PIN_PUPD_SPEC_SR(113, MSDC0_CTRL4, 4, 5, 6), +- MTK_PIN_PUPD_SPEC_SR(114, MSDC0_CTRL4, 0, 1, 2), +- MTK_PIN_PUPD_SPEC_SR(115, MSDC0_CTRL5, 0, 1, 2), +- MTK_PIN_PUPD_SPEC_SR(116, MSDC0_CTRL1, 8, 9, 10), +- MTK_PIN_PUPD_SPEC_SR(117, MSDC0_CTRL0, 8, 9, 10), +- MTK_PIN_PUPD_SPEC_SR(118, MSDC0_CTRL3, 12, 13, 14), +- MTK_PIN_PUPD_SPEC_SR(119, MSDC0_CTRL3, 8, 9, 10), +- MTK_PIN_PUPD_SPEC_SR(120, MSDC0_CTRL3, 4, 5, 6), +- MTK_PIN_PUPD_SPEC_SR(121, MSDC0_CTRL3, 0, 1, 2), +-}; +- +-static int mt7623_spec_pull_set(struct regmap *regmap, unsigned int pin, +- unsigned char align, bool isup, unsigned int r1r0) +-{ +- return mtk_pctrl_spec_pull_set_samereg(regmap, mt7623_spec_pupd, +- ARRAY_SIZE(mt7623_spec_pupd), pin, align, isup, r1r0); +-} +- +-static const struct mtk_pin_ies_smt_set mt7623_ies_set[] = { +- MTK_PIN_IES_SMT_SPEC(0, 6, IES_EN0, 0), +- MTK_PIN_IES_SMT_SPEC(7, 9, IES_EN0, 1), +- MTK_PIN_IES_SMT_SPEC(10, 13, IES_EN0, 2), +- MTK_PIN_IES_SMT_SPEC(14, 15, IES_EN0, 3), +- MTK_PIN_IES_SMT_SPEC(18, 21, IES_EN0, 5), +- MTK_PIN_IES_SMT_SPEC(22, 26, IES_EN0, 6), +- MTK_PIN_IES_SMT_SPEC(27, 29, IES_EN0, 7), +- MTK_PIN_IES_SMT_SPEC(33, 37, IES_EN0, 8), +- MTK_PIN_IES_SMT_SPEC(39, 42, IES_EN0, 9), +- MTK_PIN_IES_SMT_SPEC(43, 45, IES_EN0, 10), +- MTK_PIN_IES_SMT_SPEC(47, 48, IES_EN0, 11), +- MTK_PIN_IES_SMT_SPEC(49, 49, IES_EN0, 12), +- MTK_PIN_IES_SMT_SPEC(53, 56, IES_EN0, 14), +- MTK_PIN_IES_SMT_SPEC(60, 62, IES_EN1, 0), +- MTK_PIN_IES_SMT_SPEC(63, 65, IES_EN1, 1), +- MTK_PIN_IES_SMT_SPEC(66, 71, IES_EN1, 2), +- MTK_PIN_IES_SMT_SPEC(72, 74, IES_EN0, 12), +- MTK_PIN_IES_SMT_SPEC(75, 76, IES_EN1, 3), +- MTK_PIN_IES_SMT_SPEC(83, 84, IES_EN1, 2), +- MTK_PIN_IES_SMT_SPEC(105, 121, MSDC1_CTRL1, 4), +- MTK_PIN_IES_SMT_SPEC(122, 125, IES_EN1, 7), +- MTK_PIN_IES_SMT_SPEC(126, 126, IES_EN0, 12), +- MTK_PIN_IES_SMT_SPEC(199, 201, IES_EN0, 1), +- MTK_PIN_IES_SMT_SPEC(203, 207, IES_EN2, 2), +- MTK_PIN_IES_SMT_SPEC(208, 209, IES_EN2, 3), +- MTK_PIN_IES_SMT_SPEC(236, 241, IES_EN2, 6), +- MTK_PIN_IES_SMT_SPEC(242, 243, IES_EN2, 7), +- MTK_PIN_IES_SMT_SPEC(261, 261, MSDC1_CTRL2, 4), +- MTK_PIN_IES_SMT_SPEC(262, 272, IES_EN2, 12), +- MTK_PIN_IES_SMT_SPEC(274, 276, IES_EN2, 12), +- MTK_PIN_IES_SMT_SPEC(278, 278, IES_EN2, 13), +-}; +- +-static const struct mtk_pin_ies_smt_set mt7623_smt_set[] = { +- MTK_PIN_IES_SMT_SPEC(0, 6, SMT_EN0, 0), +- MTK_PIN_IES_SMT_SPEC(7, 9, SMT_EN0, 1), +- MTK_PIN_IES_SMT_SPEC(10, 13, SMT_EN0, 2), +- MTK_PIN_IES_SMT_SPEC(14, 15, SMT_EN0, 3), +- MTK_PIN_IES_SMT_SPEC(18, 21, SMT_EN0, 5), +- MTK_PIN_IES_SMT_SPEC(22, 26, SMT_EN0, 6), +- MTK_PIN_IES_SMT_SPEC(27, 29, SMT_EN0, 7), +- MTK_PIN_IES_SMT_SPEC(33, 37, SMT_EN0, 8), +- MTK_PIN_IES_SMT_SPEC(39, 42, SMT_EN0, 9), +- MTK_PIN_IES_SMT_SPEC(43, 45, SMT_EN0, 10), +- MTK_PIN_IES_SMT_SPEC(47, 48, SMT_EN0, 11), +- MTK_PIN_IES_SMT_SPEC(49, 49, SMT_EN0, 12), +- MTK_PIN_IES_SMT_SPEC(53, 56, SMT_EN0, 14), +- MTK_PIN_IES_SMT_SPEC(60, 62, SMT_EN1, 0), +- MTK_PIN_IES_SMT_SPEC(63, 65, SMT_EN1, 1), +- MTK_PIN_IES_SMT_SPEC(66, 71, SMT_EN1, 2), +- MTK_PIN_IES_SMT_SPEC(72, 74, SMT_EN0, 12), +- MTK_PIN_IES_SMT_SPEC(75, 76, SMT_EN1, 3), +- MTK_PIN_IES_SMT_SPEC(83, 84, SMT_EN1, 2), +- MTK_PIN_IES_SMT_SPEC(105, 106, MSDC1_CTRL1, 11), +- MTK_PIN_IES_SMT_SPEC(107, 107, MSDC1_CTRL3, 3), +- MTK_PIN_IES_SMT_SPEC(108, 108, MSDC1_CTRL3, 7), +- MTK_PIN_IES_SMT_SPEC(109, 109, MSDC1_CTRL3, 11), +- MTK_PIN_IES_SMT_SPEC(110, 111, MSDC1_CTRL3, 15), +- MTK_PIN_IES_SMT_SPEC(112, 112, MSDC0_CTRL4, 11), +- MTK_PIN_IES_SMT_SPEC(113, 113, MSDC0_CTRL4, 7), +- MTK_PIN_IES_SMT_SPEC(114, 115, MSDC0_CTRL4, 3), +- MTK_PIN_IES_SMT_SPEC(116, 117, MSDC0_CTRL1, 11), +- MTK_PIN_IES_SMT_SPEC(118, 118, MSDC0_CTRL3, 15), +- MTK_PIN_IES_SMT_SPEC(119, 119, MSDC0_CTRL3, 11), +- MTK_PIN_IES_SMT_SPEC(120, 120, MSDC0_CTRL3, 7), +- MTK_PIN_IES_SMT_SPEC(121, 121, MSDC0_CTRL3, 3), +- MTK_PIN_IES_SMT_SPEC(122, 125, SMT_EN1, 7), +- MTK_PIN_IES_SMT_SPEC(126, 126, SMT_EN0, 12), +- MTK_PIN_IES_SMT_SPEC(199, 201, SMT_EN0, 1), +- MTK_PIN_IES_SMT_SPEC(203, 207, SMT_EN2, 2), +- MTK_PIN_IES_SMT_SPEC(208, 209, SMT_EN2, 3), +- MTK_PIN_IES_SMT_SPEC(236, 241, SMT_EN2, 6), +- MTK_PIN_IES_SMT_SPEC(242, 243, SMT_EN2, 7), +- MTK_PIN_IES_SMT_SPEC(261, 261, MSDC1_CTRL6, 3), +- MTK_PIN_IES_SMT_SPEC(262, 272, SMT_EN2, 12), +- MTK_PIN_IES_SMT_SPEC(274, 276, SMT_EN2, 12), +- MTK_PIN_IES_SMT_SPEC(278, 278, SMT_EN2, 13), +-}; +- +-static int mt7623_ies_smt_set(struct regmap *regmap, unsigned int pin, +- unsigned char align, int value, enum pin_config_param arg) +-{ +- if (arg == PIN_CONFIG_INPUT_ENABLE) +- return mtk_pconf_spec_set_ies_smt_range(regmap, mt7623_ies_set, +- ARRAY_SIZE(mt7623_ies_set), pin, align, value); +- else if (arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE) +- return mtk_pconf_spec_set_ies_smt_range(regmap, mt7623_smt_set, +- ARRAY_SIZE(mt7623_smt_set), pin, align, value); +- return -EINVAL; +-} +- +-static const struct mtk_pinctrl_devdata mt7623_pinctrl_data = { +- .pins = mtk_pins_mt7623, +- .npins = ARRAY_SIZE(mtk_pins_mt7623), +- .grp_desc = mt7623_drv_grp, +- .n_grp_cls = ARRAY_SIZE(mt7623_drv_grp), +- .pin_drv_grp = mt7623_pin_drv, +- .n_pin_drv_grps = ARRAY_SIZE(mt7623_pin_drv), +- .spec_pull_set = mt7623_spec_pull_set, +- .spec_ies_smt_set = mt7623_ies_smt_set, +- .dir_offset = 0x0000, +- .pullen_offset = 0x0150, +- .pullsel_offset = 0x0280, +- .dout_offset = 0x0500, +- .din_offset = 0x0630, +- .pinmux_offset = 0x0760, +- .type1_start = 280, +- .type1_end = 280, +- .port_shf = 4, +- .port_mask = 0x1f, +- .port_align = 4, +- .eint_offsets = { +- .name = "mt7623_eint", +- .stat = 0x000, +- .ack = 0x040, +- .mask = 0x080, +- .mask_set = 0x0c0, +- .mask_clr = 0x100, +- .sens = 0x140, +- .sens_set = 0x180, +- .sens_clr = 0x1c0, +- .soft = 0x200, +- .soft_set = 0x240, +- .soft_clr = 0x280, +- .pol = 0x300, +- .pol_set = 0x340, +- .pol_clr = 0x380, +- .dom_en = 0x400, +- .dbnc_ctrl = 0x500, +- .dbnc_set = 0x600, +- .dbnc_clr = 0x700, +- .port_mask = 6, +- .ports = 6, +- }, +- .ap_num = 169, +- .db_cnt = 16, +-}; +- +-static int mt7623_pinctrl_probe(struct platform_device *pdev) +-{ +- return mtk_pctrl_init(pdev, &mt7623_pinctrl_data, NULL); +-} +- +-static const struct of_device_id mt7623_pctrl_match[] = { +- { .compatible = "mediatek,mt7623-pinctrl", }, +- {} +-}; +-MODULE_DEVICE_TABLE(of, mt7623_pctrl_match); +- +-static struct platform_driver mtk_pinctrl_driver = { +- .probe = mt7623_pinctrl_probe, +- .driver = { +- .name = "mediatek-mt7623-pinctrl", +- .of_match_table = mt7623_pctrl_match, +- }, +-}; +- +-static int __init mtk_pinctrl_init(void) +-{ +- return platform_driver_register(&mtk_pinctrl_driver); +-} +- +-arch_initcall(mtk_pinctrl_init); +--- a/include/dt-bindings/pinctrl/mt7623-pinfunc.h ++++ b/include/dt-bindings/pinctrl/mt7623-pinfunc.h +@@ -185,6 +185,12 @@ + #define MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MO (MTK_PIN_NO(56) | 1) + #define MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MI (MTK_PIN_NO(56) | 2) + ++#define MT7623_PIN_57_SDA1_FUNC_GPIO57 (MTK_PIN_NO(57) | 0) ++#define MT7623_PIN_57_SDA1_FUNC_SDA1 (MTK_PIN_NO(57) | 1) ++ ++#define MT7623_PIN_58_SCL1_FUNC_GPIO58 (MTK_PIN_NO(58) | 0) ++#define MT7623_PIN_58_SCL1_FUNC_SCL1 (MTK_PIN_NO(58) | 1) ++ + #define MT7623_PIN_60_WB_RSTB_FUNC_GPIO60 (MTK_PIN_NO(60) | 0) + #define MT7623_PIN_60_WB_RSTB_FUNC_WB_RSTB (MTK_PIN_NO(60) | 1) + +@@ -244,6 +250,22 @@ + #define MT7623_PIN_76_SCL0_FUNC_GPIO76 (MTK_PIN_NO(76) | 0) + #define MT7623_PIN_76_SCL0_FUNC_SCL0 (MTK_PIN_NO(76) | 1) + ++#define MT7623_PIN_79_URXD0_FUNC_GPIO79 (MTK_PIN_NO(79) | 0) ++#define MT7623_PIN_79_URXD0_FUNC_URXD0 (MTK_PIN_NO(79) | 1) ++#define MT7623_PIN_79_URXD0_FUNC_UTXD0 (MTK_PIN_NO(79) | 2) ++ ++#define MT7623_PIN_80_UTXD0_FUNC_GPIO80 (MTK_PIN_NO(80) | 0) ++#define MT7623_PIN_80_UTXD0_FUNC_UTXD0 (MTK_PIN_NO(80) | 1) ++#define MT7623_PIN_80_UTXD0_FUNC_URXD0 (MTK_PIN_NO(80) | 2) ++ ++#define MT7623_PIN_81_URXD1_FUNC_GPIO81 (MTK_PIN_NO(81) | 0) ++#define MT7623_PIN_81_URXD1_FUNC_URXD1 (MTK_PIN_NO(81) | 1) ++#define MT7623_PIN_81_URXD1_FUNC_UTXD1 (MTK_PIN_NO(81) | 2) ++ ++#define MT7623_PIN_82_UTXD1_FUNC_GPIO82 (MTK_PIN_NO(82) | 0) ++#define MT7623_PIN_82_UTXD1_FUNC_UTXD1 (MTK_PIN_NO(82) | 1) ++#define MT7623_PIN_82_UTXD1_FUNC_URXD1 (MTK_PIN_NO(82) | 2) ++ + #define MT7623_PIN_83_LCM_RST_FUNC_GPIO83 (MTK_PIN_NO(83) | 0) + #define MT7623_PIN_83_LCM_RST_FUNC_LCM_RST (MTK_PIN_NO(83) | 1) + +@@ -351,10 +373,10 @@ + #define MT7623_PIN_122_GPIO122_FUNC_SDA2 (MTK_PIN_NO(122) | 4) + #define MT7623_PIN_122_GPIO122_FUNC_URXD0 (MTK_PIN_NO(122) | 5) + +-#define MT7623_PIN_123_GPIO123_FUNC_GPIO123 (MTK_PIN_NO(123) | 0) +-#define MT7623_PIN_123_GPIO123_FUNC_TEST (MTK_PIN_NO(123) | 1) +-#define MT7623_PIN_123_GPIO123_FUNC_SCL2 (MTK_PIN_NO(123) | 4) +-#define MT7623_PIN_123_GPIO123_FUNC_UTXD0 (MTK_PIN_NO(123) | 5) ++#define MT7623_PIN_123_HTPLG_FUNC_GPIO123 (MTK_PIN_NO(123) | 0) ++#define MT7623_PIN_123_HTPLG_FUNC_HTPLG (MTK_PIN_NO(123) | 1) ++#define MT7623_PIN_123_HTPLG_FUNC_SCL2 (MTK_PIN_NO(123) | 4) ++#define MT7623_PIN_123_HTPLG_FUNC_UTXD0 (MTK_PIN_NO(123) | 5) + + #define MT7623_PIN_124_GPIO124_FUNC_GPIO124 (MTK_PIN_NO(124) | 0) + #define MT7623_PIN_124_GPIO124_FUNC_TEST (MTK_PIN_NO(124) | 1) diff --git a/target/linux/mediatek/patches-4.9/0059-eth-fixes.patch b/target/linux/mediatek/patches-4.9/0059-eth-fixes.patch new file mode 100644 index 0000000..61b4b26 --- /dev/null +++ b/target/linux/mediatek/patches-4.9/0059-eth-fixes.patch @@ -0,0 +1,531 @@ +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -24,6 +24,7 @@ + #include <linux/tcp.h> + + #if defined(CONFIG_NET_MEDIATEK_HW_QOS) ++ + struct mtk_ioctl_reg { + unsigned int off; + unsigned int val; +@@ -32,6 +33,13 @@ struct mtk_ioctl_reg { + #define REG_HQOS_MAX 0x3FFF + #define RAETH_QDMA_REG_READ 0x89F8 + #define RAETH_QDMA_REG_WRITE 0x89F9 ++#define RAETH_QDMA_QUEUE_MAPPING 0x89FA ++ ++unsigned int M2Q_table[16] = {0}; ++unsigned int lan_wan_separate = 0; ++ ++EXPORT_SYMBOL_GPL(M2Q_table); ++ + #endif + + #if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE) +@@ -225,7 +233,7 @@ static void mtk_phy_link_adjust(struct n + if (flowctrl & FLOW_CTRL_RX) + mcr |= MAC_MCR_FORCE_RX_FC; + +- netif_dbg(mac->hw, link, dev, "rx pause %s, tx pause %s\n", ++ netif_info(mac->hw, link, dev, "rx pause %s, tx pause %s\n", + flowctrl & FLOW_CTRL_RX ? "enabled" : "disabled", + flowctrl & FLOW_CTRL_TX ? "enabled" : "disabled"); + } +@@ -508,9 +516,9 @@ static struct rtnl_link_stats64 * mtk_ge + unsigned int start; + + if (netif_running(dev) && netif_device_present(dev)) { +- if (spin_trylock_bh(&hw_stats->stats_lock)) { ++ if (spin_trylock(&hw_stats->stats_lock)) { + mtk_stats_update_mac(mac); +- spin_unlock_bh(&hw_stats->stats_lock); ++ spin_unlock(&hw_stats->stats_lock); + } + } + +@@ -690,6 +698,7 @@ static int mtk_tx_map(struct sk_buff *sk + txd3 |= skb->mark & 0x7; + if (mac->id) + txd3 += 8; ++ txd3 = 0; + #endif + + mapped_addr = dma_map_single(eth->dev, skb->data, +@@ -760,16 +769,7 @@ static int mtk_tx_map(struct sk_buff *sk + WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) | + (!nr_frags * TX_DMA_LS0))); + +- /* we have a single DMA ring so BQL needs to be updated for all devices +- * sitting on this ring +- */ +- for (i = 0; i < MTK_MAC_COUNT; i++) { +- if (!eth->netdev[i]) +- continue; +- +- netdev_sent_queue(eth->netdev[i], skb->len); +- } +- ++ netdev_sent_queue(dev, skb->len); + skb_tx_timestamp(skb); + + ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2); +@@ -980,20 +980,9 @@ static int mtk_poll_rx(struct napi_struc + if (!(trxd.rxd2 & RX_DMA_DONE)) + break; + +- /* find out which mac the packet comes from. If the special tag is +- * we can assume that the traffic is coming from the builtin mt7530 +- * and the DSA driver has loaded. FPORT will be the physical switch +- * port in this case rather than the FE forward port id. */ +- if (!(trxd.rxd4 & RX_DMA_SP_TAG)) { +- /* values start at 1 */ +- mac = (trxd.rxd4 >> RX_DMA_FPORT_SHIFT) & +- RX_DMA_FPORT_MASK; +- mac--; +- } +- +- if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT || +- !eth->netdev[mac])) +- goto release_desc; ++ /* find out which mac the packet come from. values start at 1 */ ++ mac = (trxd.rxd4 >> 22) & 0x1; ++ mac = (mac + 1) % 2; + + netdev = eth->netdev[mac]; + +@@ -1017,6 +1006,9 @@ static int mtk_poll_rx(struct napi_struc + } + + /* receive data */ ++ if (mac < 0 || mac > 2) ++ mac = 0; ++ + skb = build_skb(data, ring->frag_size); + if (unlikely(!skb)) { + skb_free_frag(new_data); +@@ -1076,18 +1068,21 @@ static int mtk_poll_tx(struct mtk_eth *e + struct mtk_tx_dma *desc; + struct sk_buff *skb; + struct mtk_tx_buf *tx_buf; +- int total = 0, done = 0; +- unsigned int bytes = 0; ++ unsigned int done[MTK_MAX_DEVS]; ++ unsigned int bytes[MTK_MAX_DEVS]; + u32 cpu, dma; + static int condition; +- int i; ++ int total = 0, i; ++ ++ memset(done, 0, sizeof(done)); ++ memset(bytes, 0, sizeof(bytes)); + + cpu = mtk_r32(eth, MTK_QTX_CRX_PTR); + dma = mtk_r32(eth, MTK_QTX_DRX_PTR); + + desc = mtk_qdma_phys_to_virt(ring, cpu); + +- while ((cpu != dma) && done < budget) { ++ while ((cpu != dma) && budget) { + u32 next_cpu = desc->txd2; + int mac = 0; + +@@ -1106,8 +1101,9 @@ static int mtk_poll_tx(struct mtk_eth *e + } + + if (skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC) { +- bytes += skb->len; +- done++; ++ bytes[mac] += skb->len; ++ done[mac]++; ++ budget--; + } + mtk_tx_unmap(eth, tx_buf); + +@@ -1119,13 +1115,11 @@ static int mtk_poll_tx(struct mtk_eth *e + + mtk_w32(eth, cpu, MTK_QTX_CRX_PTR); + +- /* we have a single DMA ring so BQL needs to be updated for all devices +- * sitting on this ring +- */ + for (i = 0; i < MTK_MAC_COUNT; i++) { +- if (!eth->netdev[i]) ++ if (!eth->netdev[i] || !done[i]) + continue; +- netdev_completed_queue(eth->netdev[i], done, bytes); ++ netdev_completed_queue(eth->netdev[i], done[i], bytes[i]); ++ total += done[i]; + } + + if (mtk_queue_stopped(eth) && +@@ -1286,21 +1280,11 @@ static void mtk_tx_clean(struct mtk_eth + + static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) + { +- struct mtk_rx_ring *ring; ++ struct mtk_rx_ring *ring = ð->rx_ring[ring_no]; + int rx_data_len, rx_dma_size; + int i; +- u32 offset = 0; +- +- if (rx_flag & MTK_RX_FLAGS_QDMA) { +- if (ring_no) +- return -EINVAL; +- ring = ð->rx_ring_qdma; +- offset = 0x1000; +- } else { +- ring = ð->rx_ring[ring_no]; +- } + +- if (rx_flag & MTK_RX_FLAGS_HWLRO) { ++ if (rx_flag == MTK_RX_FLAGS_HWLRO) { + rx_data_len = MTK_MAX_LRO_RX_LENGTH; + rx_dma_size = MTK_HW_LRO_DMA_SIZE; + } else { +@@ -1348,16 +1332,104 @@ static int mtk_rx_alloc(struct mtk_eth * + */ + wmb(); + +- mtk_w32(eth, ring->phys, MTK_PRX_BASE_PTR_CFG(ring_no) + offset); +- mtk_w32(eth, rx_dma_size, MTK_PRX_MAX_CNT_CFG(ring_no) + offset); +- mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg + offset); +- mtk_w32(eth, MTK_PST_DRX_IDX_CFG(ring_no), MTK_PDMA_RST_IDX + offset); ++ mtk_w32(eth, ring->phys, MTK_PRX_BASE_PTR_CFG(ring_no)); ++ mtk_w32(eth, rx_dma_size, MTK_PRX_MAX_CNT_CFG(ring_no)); ++ mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg); ++ mtk_w32(eth, MTK_PST_DRX_IDX_CFG(ring_no), MTK_PDMA_RST_IDX); + + return 0; + } + +-static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring) ++static int mtk_rx_alloc_qdma(struct mtk_eth *eth, int rx_flag) + { ++ struct mtk_rx_ring *ring = ð->rx_ring_qdma; ++ int rx_data_len, rx_dma_size; ++ int i; ++ ++ rx_data_len = ETH_DATA_LEN; ++ rx_dma_size = MTK_DMA_SIZE; ++ ++ ring->frag_size = mtk_max_frag_size(rx_data_len); ++ ring->buf_size = mtk_max_buf_size(ring->frag_size); ++ ring->data = kcalloc(rx_dma_size, sizeof(*ring->data), ++ GFP_KERNEL); ++ if (!ring->data) ++ return -ENOMEM; ++ ++ for (i = 0; i < rx_dma_size; i++) { ++ ring->data[i] = netdev_alloc_frag(ring->frag_size); ++ if (!ring->data[i]) ++ return -ENOMEM; ++ } ++ ++ ring->dma = dma_alloc_coherent(eth->dev, ++ rx_dma_size * sizeof(*ring->dma), ++ &ring->phys, ++ GFP_ATOMIC | __GFP_ZERO); ++ if (!ring->dma) ++ return -ENOMEM; ++ ++ for (i = 0; i < rx_dma_size; i++) { ++ dma_addr_t dma_addr = dma_map_single(eth->dev, ++ ring->data[i] + NET_SKB_PAD, ++ ring->buf_size, ++ DMA_FROM_DEVICE); ++ if (unlikely(dma_mapping_error(eth->dev, dma_addr))) ++ return -ENOMEM; ++ ring->dma[i].rxd1 = (unsigned int)dma_addr; ++ ++ ring->dma[i].rxd2 = RX_DMA_PLEN0(ring->buf_size); ++ } ++ ring->dma_size = rx_dma_size; ++ ring->calc_idx_update = false; ++ ring->calc_idx = rx_dma_size - 1; ++ ring->crx_idx_reg = MTK_QRX_CRX_IDX_CFG(0); ++ /* make sure that all changes to the dma ring are flushed before we ++ * continue ++ */ ++ wmb(); ++ ++ mtk_w32(eth, ring->phys, MTK_QRX_BASE_PTR_CFG(0)); ++ mtk_w32(eth, rx_dma_size, MTK_QRX_MAX_CNT_CFG(0)); ++ mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg); ++ mtk_w32(eth, MTK_PST_DRX_IDX_CFG(0), MTK_QDMA_RST_IDX); ++ ++ return 0; ++} ++ ++static void mtk_rx_clean(struct mtk_eth *eth, int ring_no) ++{ ++ struct mtk_rx_ring *ring = ð->rx_ring[ring_no]; ++ int i; ++ ++ if (ring->data && ring->dma) { ++ for (i = 0; i < ring->dma_size; i++) { ++ if (!ring->data[i]) ++ continue; ++ if (!ring->dma[i].rxd1) ++ continue; ++ dma_unmap_single(eth->dev, ++ ring->dma[i].rxd1, ++ ring->buf_size, ++ DMA_FROM_DEVICE); ++ skb_free_frag(ring->data[i]); ++ } ++ kfree(ring->data); ++ ring->data = NULL; ++ } ++ ++ if (ring->dma) { ++ dma_free_coherent(eth->dev, ++ ring->dma_size * sizeof(*ring->dma), ++ ring->dma, ++ ring->phys); ++ ring->dma = NULL; ++ } ++} ++ ++static void mtk_rx_clean_qdma(struct mtk_eth *eth) ++{ ++ struct mtk_rx_ring *ring = ð->rx_ring_qdma; + int i; + + if (ring->data && ring->dma) { +@@ -1683,7 +1755,7 @@ static int mtk_dma_init(struct mtk_eth * + if (err) + return err; + +- err = mtk_rx_alloc(eth, 0, MTK_RX_FLAGS_QDMA); ++ err = mtk_rx_alloc_qdma(eth, MTK_RX_FLAGS_NORMAL); + if (err) + return err; + +@@ -1702,6 +1774,7 @@ static int mtk_dma_init(struct mtk_eth * + return err; + } + ++ + /* Enable random early drop and set drop threshold automatically */ + mtk_w32(eth, FC_THRES_DROP_MODE | FC_THRES_DROP_EN | FC_THRES_MIN, + MTK_QDMA_FC_THRES); +@@ -1726,13 +1799,13 @@ static void mtk_dma_free(struct mtk_eth + eth->phy_scratch_ring = 0; + } + mtk_tx_clean(eth); +- mtk_rx_clean(eth, ð->rx_ring[0]); +- mtk_rx_clean(eth, ð->rx_ring_qdma); ++ mtk_rx_clean(eth, 0); ++ mtk_rx_clean_qdma(eth); + + if (eth->hwlro) { + mtk_hwlro_rx_uninit(eth); + for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) +- mtk_rx_clean(eth, ð->rx_ring[i]); ++ mtk_rx_clean(eth, i); + } + + kfree(eth->scratch_head); +@@ -1947,20 +2020,14 @@ static int mtk_hw_init(struct mtk_eth *e + val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); + mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); + +- /* Indicates CDM to parse the MTK special tag from CPU +- * which also is working out for untag packets. +- */ +- val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); +- mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); +- val = mtk_r32(eth, MTK_CDMP_IG_CTRL); +- mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); +- + /* Enable RX VLan Offloading */ + if (MTK_HW_FEATURES & NETIF_F_HW_VLAN_CTAG_RX) + mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); + else + mtk_w32(eth, 0, MTK_CDMP_EG_CTRL); + ++ mtk_w32(eth, 0x81000001, MTK_CDMP_IG_CTRL); ++ + /* disable delay and normal interrupt */ + #ifdef MTK_IRQ_DLY + mtk_w32(eth, 0x84048404, MTK_PDMA_DELAY_INT); +@@ -1990,6 +2057,9 @@ static int mtk_hw_init(struct mtk_eth *e + /* Enable RX checksum */ + val |= MTK_GDMA_ICS_EN | MTK_GDMA_TCS_EN | MTK_GDMA_UCS_EN; + ++ if (!i) ++ val |= BIT(24); ++ + /* setup the mac dma */ + mtk_w32(eth, val, MTK_GDMA_FWD_CFG(i)); + } +@@ -2069,7 +2139,18 @@ static int mtk_do_ioctl(struct net_devic + if (reg.off > REG_HQOS_MAX) + return -EINVAL; + mtk_w32(eth, reg.val, 0x1800 + reg.off); +-// printk("write reg off:%x val:%x\n", reg.off, reg.val); ++ printk("write reg off:%x val:%x\n", reg.off, reg.val); ++ return 0; ++ ++ case RAETH_QDMA_QUEUE_MAPPING: ++ copy_from_user(®, ifr->ifr_data, sizeof(reg)); ++ if ((reg.off & 0x100) == 0x100) { ++ lan_wan_separate = 1; ++ reg.off &= 0xff; ++ } else { ++ lan_wan_separate = 0; ++ } ++ M2Q_table[reg.off] = reg.val; + return 0; + #endif + case SIOCGMIIPHY: +@@ -2288,9 +2369,9 @@ static void mtk_get_ethtool_stats(struct + return; + + if (netif_running(dev) && netif_device_present(dev)) { +- if (spin_trylock_bh(&hwstats->stats_lock)) { ++ if (spin_trylock(&hwstats->stats_lock)) { + mtk_stats_update_mac(mac); +- spin_unlock_bh(&hwstats->stats_lock); ++ spin_unlock(&hwstats->stats_lock); + } + } + +@@ -2443,7 +2524,7 @@ static int mtk_add_mac(struct mtk_eth *e + mac->hw_stats->reg_offset = id * MTK_STAT_OFFSET; + + SET_NETDEV_DEV(eth->netdev[id], eth->dev); +- eth->netdev[id]->watchdog_timeo = 30 * HZ; ++ eth->netdev[id]->watchdog_timeo = 15 * HZ; + eth->netdev[id]->netdev_ops = &mtk_netdev_ops; + eth->netdev[id]->base_addr = (unsigned long)eth->base; + +@@ -2584,15 +2665,19 @@ static int mtk_probe(struct platform_dev + goto err_deinit_hw; + } + ++ cpumask_set_cpu(1, ð->affinity_mask[1]); ++ cpumask_set_cpu(0, ð->affinity_mask[2]); + err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0, + dev_name(eth->dev), eth); + if (err) + goto err_free_dev; ++ irq_set_affinity_hint(eth->irq[1], ð->affinity_mask[1]); + + err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0, + dev_name(eth->dev), eth); + if (err) + goto err_free_dev; ++ irq_set_affinity_hint(eth->irq[2], ð->affinity_mask[2]); + + err = mtk_mdio_init(eth); + if (err) +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -80,7 +80,6 @@ + + /* CDMP Ingress Control Register */ + #define MTK_CDMP_IG_CTRL 0x400 +-#define MTK_CDMP_STAG_EN BIT(0) + + /* CDMP Exgress Control Register */ + #define MTK_CDMP_EG_CTRL 0x404 +@@ -91,12 +90,27 @@ + #define MTK_GDMA_TCS_EN BIT(21) + #define MTK_GDMA_UCS_EN BIT(20) + ++/* GDMA Ingress Control Register */ ++#define MTK_GDMA1_IG_CTRL(x) (0x500 + (x * 0x1000)) ++ + /* Unicast Filter MAC Address Register - Low */ + #define MTK_GDMA_MAC_ADRL(x) (0x508 + (x * 0x1000)) + + /* Unicast Filter MAC Address Register - High */ + #define MTK_GDMA_MAC_ADRH(x) (0x50C + (x * 0x1000)) + ++/* QDMA RX Base Pointer Register */ ++#define MTK_QRX_BASE_PTR0 0x1900 ++#define MTK_QRX_BASE_PTR_CFG(x) (MTK_QRX_BASE_PTR0 + (x * 0x10)) ++ ++/* QDMA RX Maximum Count Register */ ++#define MTK_QRX_MAX_CNT0 0x1904 ++#define MTK_QRX_MAX_CNT_CFG(x) (MTK_QRX_MAX_CNT0 + (x * 0x10)) ++ ++/* QDMA RX CPU Pointer Register */ ++#define MTK_QRX_CRX_IDX0 0x1908 ++#define MTK_QRX_CRX_IDX_CFG(x) (MTK_QRX_CRX_IDX0 + (x * 0x10)) ++ + /* PDMA RX Base Pointer Register */ + #define MTK_PRX_BASE_PTR0 0x900 + #define MTK_PRX_BASE_PTR_CFG(x) (MTK_PRX_BASE_PTR0 + (x * 0x10)) +@@ -240,7 +254,10 @@ + #define MTK_QDMA_INT_MASK 0x1A1C + + /* QDMA Interrupt Mask Register */ ++#define MTK_QDMA_HRED1 0x1A40 + #define MTK_QDMA_HRED2 0x1A44 ++#define MTK_QDMA_SRED1 0x1A48 ++#define MTK_QDMA_SRED2 0x1A4c + + /* QDMA TX Forward CPU Pointer Register */ + #define MTK_QTX_CTX_PTR 0x1B00 +@@ -275,6 +292,7 @@ + #define TX_DMA_TSO BIT(28) + #define TX_DMA_FPORT_SHIFT 25 + #define TX_DMA_FPORT_MASK 0x7 ++#define TX_DMA_VQID0 BIT(17) + #define TX_DMA_INS_VLAN BIT(16) + + /* QDMA descriptor txd3 */ +@@ -294,7 +312,6 @@ + + /* QDMA descriptor rxd4 */ + #define RX_DMA_L4_VALID BIT(24) +-#define RX_DMA_SP_TAG BIT(22) + #define RX_DMA_FPORT_SHIFT 19 + #define RX_DMA_FPORT_MASK 0x7 + +@@ -310,6 +327,7 @@ + + /* Mac control registers */ + #define MTK_MAC_MCR(x) (0x10100 + (x * 0x100)) ++#define MTK_MAC_MSR(x) (0x10108 + (x * 0x100)) + #define MAC_MCR_MAX_RX_1536 BIT(24) + #define MAC_MCR_IPG_CFG (BIT(18) | BIT(16)) + #define MAC_MCR_FORCE_MODE BIT(15) +@@ -495,7 +513,6 @@ struct mtk_tx_ring { + enum mtk_rx_flags { + MTK_RX_FLAGS_NORMAL = 0, + MTK_RX_FLAGS_HWLRO, +- MTK_RX_FLAGS_QDMA, + }; + + /* struct mtk_rx_ring - This struct holds info describing a RX ring +@@ -539,9 +556,9 @@ struct mtk_rx_ring { + * @pctl: The register map pointing at the range used to setup + * GMAC port drive/slew values + * @dma_refcnt: track how many netdevs are using the DMA engine +- * @tx_ring: Pointer to the memory holding info about the TX ring +- * @rx_ring: Pointer to the memory holding info about the RX ring +- * @rx_ring_qdma: Pointer to the memory holding info about the QDMA RX ring ++ * @tx_ring: Pointer to the memore holding info about the TX ring ++ * @rx_ring: Pointer to the memore holding info about the RX ring ++ * @rx_ring_qdma: Pointer to the memore holding info about the RX ring (QDMA) + * @tx_napi: The TX NAPI struct + * @rx_napi: The RX NAPI struct + * @scratch_ring: Newer SoCs need memory for a second HW managed TX ring +@@ -563,6 +580,7 @@ struct mtk_eth { + struct net_device *netdev[MTK_MAX_DEVS]; + struct mtk_mac *mac[MTK_MAX_DEVS]; + int irq[3]; ++ cpumask_t affinity_mask[3]; + u32 msg_enable; + unsigned long sysclk; + struct regmap *ethsys; +@@ -615,4 +633,6 @@ void mtk_stats_update_mac(struct mtk_mac + void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg); + u32 mtk_r32(struct mtk_eth *eth, unsigned reg); + ++extern unsigned int M2Q_table[16]; ++ + #endif /* MTK_ETH_H */ diff --git a/target/linux/mediatek/patches-4.9/0083-mfd-led3.patch b/target/linux/mediatek/patches-4.9/0083-mfd-led3.patch deleted file mode 100644 index f743e10..0000000 --- a/target/linux/mediatek/patches-4.9/0083-mfd-led3.patch +++ /dev/null @@ -1,41 +0,0 @@ -From patchwork Fri Feb 24 18:47:21 2017 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v4,4/4] mfd: mt6397: Add MT6323 LED support into MT6397 driver -From: sean.wang@mediatek.com -X-Patchwork-Id: 9591021 -Message-Id: <1487962041-6548-5-git-send-email-sean.wang@mediatek.com> -To: <rpurdie@rpsys.net>, <jacek.anaszewski@gmail.com>, <lee.jones@linaro.org>, - <matthias.bgg@gmail.com>, <pavel@ucw.cz>, <robh+dt@kernel.org>, - <mark.rutland@arm.com> -Cc: devicetree@vger.kernel.org, keyhaede@gmail.com, - Sean Wang <sean.wang@mediatek.com>, linux-kernel@vger.kernel.org, - linux-mediatek@lists.infradead.org, linux-leds@vger.kernel.org, - linux-arm-kernel@lists.infradead.org -Date: Sat, 25 Feb 2017 02:47:21 +0800 - -From: Sean Wang <sean.wang@mediatek.com> - -Add compatible string as "mt6323-led" that will make -the OF core spawn child devices for the LED subnode -of that MT6323 MFD device. - -Signed-off-by: Sean Wang <sean.wang@mediatek.com> ---- - drivers/mfd/mt6397-core.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/mfd/mt6397-core.c -+++ b/drivers/mfd/mt6397-core.c -@@ -48,6 +48,10 @@ static const struct mfd_cell mt6323_devs - .name = "mt6323-regulator", - .of_compatible = "mediatek,mt6323-regulator" - }, -+ { -+ .name = "mt6323-led", -+ .of_compatible = "mediatek,mt6323-led" -+ }, - }; - - static const struct mfd_cell mt6397_devs[] = { diff --git a/target/linux/mediatek/patches-4.9/0086-pmic-led1.patch b/target/linux/mediatek/patches-4.9/0086-pmic-led1.patch deleted file mode 100644 index 2edb4ba..0000000 --- a/target/linux/mediatek/patches-4.9/0086-pmic-led1.patch +++ /dev/null @@ -1,38 +0,0 @@ -From patchwork Mon Mar 20 06:47:25 2017 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v6, - 2/4] dt-bindings: mfd: Add the description for LED as the sub module -From: sean.wang@mediatek.com -X-Patchwork-Id: 9633089 -Message-Id: <1489992447-13007-3-git-send-email-sean.wang@mediatek.com> -To: <rpurdie@rpsys.net>, <jacek.anaszewski@gmail.com>, <lee.jones@linaro.org>, - <matthias.bgg@gmail.com>, <pavel@ucw.cz>, <robh+dt@kernel.org>, - <mark.rutland@arm.com> -Cc: devicetree@vger.kernel.org, keyhaede@gmail.com, - Sean Wang <sean.wang@mediatek.com>, linux-kernel@vger.kernel.org, - linux-mediatek@lists.infradead.org, linux-leds@vger.kernel.org, - linux-arm-kernel@lists.infradead.org -Date: Mon, 20 Mar 2017 14:47:25 +0800 - -From: Sean Wang <sean.wang@mediatek.com> - -This patch adds description for LED as the sub-module on MT6397/MT6323 -multifunction device. - -Signed-off-by: Sean Wang <sean.wang@mediatek.com> ---- - Documentation/devicetree/bindings/mfd/mt6397.txt | 1 + - 1 file changed, 1 insertion(+) - ---- a/Documentation/devicetree/bindings/mfd/mt6397.txt -+++ b/Documentation/devicetree/bindings/mfd/mt6397.txt -@@ -6,6 +6,7 @@ MT6397/MT6323 is a multifunction device - - Audio codec - - GPIO - - Clock -+- LED - - It is interfaced to host controller using SPI interface by a proprietary hardware - called PMIC wrapper or pwrap. MT6397/MT6323 MFD is a child device of pwrap. diff --git a/target/linux/mediatek/patches-4.9/0088-pmic-led3.patch b/target/linux/mediatek/patches-4.9/0088-pmic-led3.patch deleted file mode 100644 index 888218b..0000000 --- a/target/linux/mediatek/patches-4.9/0088-pmic-led3.patch +++ /dev/null @@ -1,42 +0,0 @@ -From patchwork Mon Mar 20 06:47:27 2017 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v6, - 4/4] mfd: mt6397: Align the placement at which the mfd_cell of LED is - defined -From: sean.wang@mediatek.com -X-Patchwork-Id: 9633079 -Message-Id: <1489992447-13007-5-git-send-email-sean.wang@mediatek.com> -To: <rpurdie@rpsys.net>, <jacek.anaszewski@gmail.com>, <lee.jones@linaro.org>, - <matthias.bgg@gmail.com>, <pavel@ucw.cz>, <robh+dt@kernel.org>, - <mark.rutland@arm.com> -Cc: devicetree@vger.kernel.org, keyhaede@gmail.com, - Sean Wang <sean.wang@mediatek.com>, linux-kernel@vger.kernel.org, - linux-mediatek@lists.infradead.org, linux-leds@vger.kernel.org, - linux-arm-kernel@lists.infradead.org -Date: Mon, 20 Mar 2017 14:47:27 +0800 - -From: Sean Wang <sean.wang@mediatek.com> - -Align the placement as which the mfd_cell of LED is defined as the other -members done on the structure. - -Signed-off-by: Sean Wang <sean.wang@mediatek.com> -Acked-by: Lee Jones <lee.jones@linaro.org> ---- - drivers/mfd/mt6397-core.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/mfd/mt6397-core.c -+++ b/drivers/mfd/mt6397-core.c -@@ -47,8 +47,7 @@ static const struct mfd_cell mt6323_devs - { - .name = "mt6323-regulator", - .of_compatible = "mediatek,mt6323-regulator" -- }, -- { -+ }, { - .name = "mt6323-led", - .of_compatible = "mediatek,mt6323-led" - }, diff --git a/target/linux/mediatek/patches-4.9/0092-dsa4.patch b/target/linux/mediatek/patches-4.9/0092-dsa4.patch deleted file mode 100644 index 4daebfb..0000000 --- a/target/linux/mediatek/patches-4.9/0092-dsa4.patch +++ /dev/null @@ -1,44 +0,0 @@ -From patchwork Wed Mar 29 09:38:22 2017 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [net-next, v3, - 4/5] net-next: ethernet: mediatek: add device_node of GMAC pointing - into the netdev instance -From: sean.wang@mediatek.com -X-Patchwork-Id: 9651097 -Message-Id: <1490780303-18598-5-git-send-email-sean.wang@mediatek.com> -To: <andrew@lunn.ch>, <f.fainelli@gmail.com>, - <vivien.didelot@savoirfairelinux.com>, <matthias.bgg@gmail.com>, - <robh+dt@kernel.org>, <mark.rutland@arm.com> -Cc: devicetree@vger.kernel.org, Landen.Chao@mediatek.com, keyhaede@gmail.com, - netdev@vger.kernel.org, sean.wang@mediatek.com, - linux-kernel@vger.kernel.org, - linux-mediatek@lists.infradead.org, objelf@gmail.com, davem@davemloft.net -Date: Wed, 29 Mar 2017 17:38:22 +0800 - -From: Sean Wang <sean.wang@mediatek.com> - -the patch adds the setup of the corresponding device node of GMAC into the -netdev instance which could allow other modules such as DSA to find the -instance through the node in dt-bindings using of_find_net_device_by_node() -call. - -Signed-off-by: Sean Wang <sean.wang@mediatek.com> -Reviewed-by: Andrew Lunn <andrew@lunn.ch> -Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> ---- - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2333,6 +2333,8 @@ static int mtk_add_mac(struct mtk_eth *e - eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops; - - eth->netdev[id]->irq = eth->irq[0]; -+ eth->netdev[id]->dev.of_node = np; -+ - return 0; - - free_netdev: diff --git a/target/linux/mediatek/patches-4.9/0094-net-affinity.patch b/target/linux/mediatek/patches-4.9/0094-net-affinity.patch deleted file mode 100644 index 0c468fb..0000000 --- a/target/linux/mediatek/patches-4.9/0094-net-affinity.patch +++ /dev/null @@ -1,36 +0,0 @@ ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -2459,15 +2459,23 @@ static int mtk_probe(struct platform_dev - goto err_deinit_hw; - } - -+ for (i = 0; i < 3; i++) { -+ int cpu = i % num_online_cpus(); -+ -+ cpumask_set_cpu(cpu, ð->affinity_mask[i]); -+ } -+ - err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0, - dev_name(eth->dev), eth); - if (err) - goto err_free_dev; -+ irq_set_affinity_hint(eth->irq[1], ð->affinity_mask[1]); - - err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0, - dev_name(eth->dev), eth); - if (err) - goto err_free_dev; -+ irq_set_affinity_hint(eth->irq[2], ð->affinity_mask[2]); - - err = mtk_mdio_init(eth); - if (err) ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -539,6 +539,7 @@ struct mtk_eth { - struct net_device *netdev[MTK_MAX_DEVS]; - struct mtk_mac *mac[MTK_MAX_DEVS]; - int irq[3]; -+ cpumask_t affinity_mask[3]; - u32 msg_enable; - unsigned long sysclk; - struct regmap *ethsys; diff --git a/target/linux/mediatek/patches-4.9/0200-devicetree.patch b/target/linux/mediatek/patches-4.9/0200-devicetree.patch deleted file mode 100644 index 4eca20a..0000000 --- a/target/linux/mediatek/patches-4.9/0200-devicetree.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -950,6 +950,9 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ - mt6589-aquaris5.dtb \ - mt6592-evb.dtb \ - mt7623-evb.dtb \ -+ mt7623-eMMC.dtb \ -+ mt7623-NAND.dtb \ -+ mt7623-NAND-ePHY.dtb \ - mt8127-moose.dtb \ - mt8135-evbp1.dtb - dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb diff --git a/target/linux/mediatek/patches-4.9/0201-block2mtd.patch b/target/linux/mediatek/patches-4.9/0201-block2mtd.patch deleted file mode 100644 index 395884b..0000000 --- a/target/linux/mediatek/patches-4.9/0201-block2mtd.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- a/drivers/mtd/devices/block2mtd.c -+++ b/drivers/mtd/devices/block2mtd.c -@@ -32,6 +32,8 @@ - #include <linux/slab.h> - #include <linux/major.h> - -+static const char * const block2mtd_probe_types[] = { "cmdlinepart", NULL }; -+ - /* Info for the block device */ - struct block2mtd_dev { - struct list_head list; -@@ -227,6 +229,7 @@ static struct block2mtd_dev *add_device( - #endif - const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; - struct block_device *bdev = ERR_PTR(-ENODEV); -+ struct mtd_part_parser_data ppdata = { 0 }; - struct block2mtd_dev *dev; - struct mtd_partition *part; - char *name; -@@ -307,11 +310,7 @@ static struct block2mtd_dev *add_device( - dev->mtd.priv = dev; - dev->mtd.owner = THIS_MODULE; - -- part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL); -- part->name = name; -- part->offset = 0; -- part->size = dev->mtd.size; -- if (mtd_device_register(&dev->mtd, part, 1)) { -+ if (mtd_device_parse_register(&dev->mtd, block2mtd_probe_types, &ppdata, NULL, 0)) { - /* Device didn't get added, so free the entry */ - goto err_destroy_mutex; - } |