diff options
Diffstat (limited to 'target/linux/mediatek/patches-4.9')
63 files changed, 0 insertions, 13075 deletions
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 deleted file mode 100644 index ff04a9f..0000000 --- a/target/linux/mediatek/patches-4.9/0001-arch-arm-add-dts-build-code.patch +++ /dev/null @@ -1,23 +0,0 @@ -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/0002-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch b/target/linux/mediatek/patches-4.9/0002-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch deleted file mode 100644 index 9dd6fcd..0000000 --- a/target/linux/mediatek/patches-4.9/0002-dt-bindings-add-MediaTek-PCIe-binding-documentation.patch +++ /dev/null @@ -1,154 +0,0 @@ -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 02/57] dt-bindings: add MediaTek PCIe binding documentation - -Signed-off-by: John Crispin <blogic@openwrt.org> ---- - .../devicetree/bindings/pci/mediatek-pcie.txt | 140 +++++++++++++++++++++ - 1 file changed, 140 insertions(+) - create mode 100644 Documentation/devicetree/bindings/pci/mediatek-pcie.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/pci/mediatek-pcie.txt -@@ -0,0 +1,140 @@ -+Mediatek PCIe controller -+ -+Required properties: -+- compatible: Should be one of: -+ - "mediatek,mt2701-pcie" -+ - "mediatek,mt7623-pcie" -+- device_type: Must be "pci" -+- reg: A list of physical base address and length for each set of controller -+ registers. A list of register ranges to use. Must contain an -+ entry for each entry in the reg-names property. -+- reg-names: Must include the following entries: -+ "pcie": PCIe registers -+ "pcie phy0": PCIe PHY0 registers -+ "pcie phy1": PCIe PHY0 registers -+ "pcie phy2": PCIe PHY0 registers -+- interrupts: A list of interrupt outputs of the controller. Must contain an -+ entry for each entry in the interrupt-names property. -+- interrupt-names: Must include the following entries: -+ "pcie0": The interrupt that is asserted for port0 -+ "pcie1": The interrupt that is asserted for port1 -+ "pcie2": The interrupt that is asserted for port2 -+- bus-range: Range of bus numbers associated with this controller -+- #address-cells: Address representation for root ports (must be 3) -+- #size-cells: Size representation for root ports (must be 2) -+- ranges: Describes the translation of addresses for root ports and standard -+ PCI regions. The entries must be 6 cells each. -+ Please refer to the standard PCI bus binding document for a more detailed -+ explanation. -+- #interrupt-cells: Size representation for interrupts (must be 1) -+- clocks: Must contain an entry for each entry in clock-names. -+ See ../clocks/clock-bindings.txt for details. -+- clock-names: Must include the following entries: -+ - pcie0 -+ - pcie1 -+ - pcie2 -+- resets: Must contain an entry for each entry in reset-names. -+ See ../reset/reset.txt for details. -+- reset-names: Must include the following entries: -+ - pcie0 -+ - pcie1 -+ - pcie2 -+- mediatek,hifsys: Must contain a phandle to the HIFSYS syscon range. -+Root ports are defined as subnodes of the PCIe controller node. -+ -+Required properties: -+- device_type: Must be "pci" -+- assigned-addresses: Address and size of the port configuration registers -+- reg: PCI bus address of the root port -+- #address-cells: Must be 3 -+- #size-cells: Must be 2 -+- ranges: Sub-ranges distributed from the PCIe controller node. An empty -+ property is sufficient. -+ -+Example: -+ -+SoC DTSI: -+ -+ hifsys: clock-controller@1a000000 { -+ compatible = "mediatek,mt7623-hifsys", -+ "mediatek,mt2701-hifsys", -+ "syscon"; -+ reg = <0 0x1a000000 0 0x1000>; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ }; -+ -+ pcie-controller@1a140000 { -+ compatible = "mediatek,mt7623-pcie"; -+ device_type = "pci"; -+ reg = <0 0x1a140000 0 0x8000>, /* PCI-Express registers */ -+ <0 0x1a149000 0 0x1000>, /* PCI-Express PHY0 */ -+ <0 0x1a14a000 0 0x1000>, /* PCI-Express PHY1 */ -+ <0 0x1a244000 0 0x1000>; /* PCI-Express PHY2 */ -+ reg-names = "pcie", "pcie phy0", "pcie phy1", "pcie phy2"; -+ interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>, -+ <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>, -+ <GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>; -+ interrupt-names = "pcie0", "pcie1", "pcie2"; -+ clocks = <&topckgen CLK_TOP_ETHIF_SEL>; -+ clock-names = "pcie"; -+ power-domains = <&scpsys MT2701_POWER_DOMAIN_HIF>; -+ resets = <&hifsys MT2701_HIFSYS_PCIE0_RST>, -+ <&hifsys MT2701_HIFSYS_PCIE1_RST>, -+ <&hifsys MT2701_HIFSYS_PCIE2_RST>; -+ reset-names = "pcie0", "pice1", "pcie2"; -+ -+ bus-range = <0x00 0xff>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ -+ mediatek,hifsys = <&hifsys>; -+ -+ ranges = <0x81000000 0 0x1a160000 0 0x1a160000 0 0x00010000 /* io space */ -+ 0x83000000 0 0x60000000 0 0x60000000 0 0x10000000>; /* pci memory */ -+ -+ status = "disabled"; -+ -+ pcie@1,0 { -+ device_type = "pci"; -+ reg = <0x0800 0 0 0 0>; -+ -+ #address-cells = <3>; -+ #size-cells = <2>; -+ ranges; -+ -+ status = "disabled"; -+ }; -+ -+ pcie@2,0{ -+ device_type = "pci"; -+ reg = <0x1000 0 0 0 0>; -+ -+ #address-cells = <3>; -+ #size-cells = <2>; -+ ranges; -+ -+ status = "disabled"; -+ }; -+ -+ pcie@3,0{ -+ device_type = "pci"; -+ reg = <0x1800 0 0 0 0>; -+ -+ #address-cells = <3>; -+ #size-cells = <2>; -+ ranges; -+ -+ status = "disabled"; -+ }; -+ }; -+ -+Board DTS: -+ -+ pcie-controller { -+ status = "okay"; -+ -+ pci@1,0 { -+ status = "okay"; -+ }; -+ }; diff --git a/target/linux/mediatek/patches-4.9/0003-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 deleted file mode 100644 index 43f51ef..0000000 --- a/target/linux/mediatek/patches-4.9/0003-PCI-mediatek-add-support-for-PCIe-found-on-MT7623-MT.patch +++ /dev/null @@ -1,698 +0,0 @@ -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 03/57] PCI: mediatek: add support for PCIe found on - MT7623/MT2701 - -Add PCIe controller support on MediaTek MT2701/MT7623. The driver supports -a single Root complex (RC) with 3 Root Ports. The SoCs supports a Gen2 -1-lan Link on each port. - -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 +++++++++++++++++++++++++++++++++++++++ - 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 -@@ -25,6 +25,7 @@ config MACH_MT6592 - config MACH_MT7623 - bool "MediaTek MT7623 SoCs support" - default ARCH_MEDIATEK -+ select MIGHT_HAVE_PCI - - config MACH_MT8127 - bool "MediaTek MT8127 SoCs support" ---- a/drivers/pci/host/Kconfig -+++ b/drivers/pci/host/Kconfig -@@ -301,4 +301,15 @@ config VMD - To compile this driver as a module, choose M here: the - module will be called vmd. - -+config PCIE_MTK -+ bool "Mediatek PCIe Controller" -+ depends on MACH_MT2701 || MACH_MT7623 -+ depends on OF -+ depends on PCI -+ help -+ Say Y here if you want to enable PCI controller support on Mediatek MT7623. -+ MT7623 PCIe supports single Root complex (RC) with 3 Root Ports. -+ Each port supports a Gen2 1-lan Link. -+ PCIe include one Host/PCI bridge and 3 PCIe MAC. -+ - endmenu ---- a/drivers/pci/host/Makefile -+++ b/drivers/pci/host/Makefile -@@ -33,3 +33,4 @@ obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-arm - obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o - obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o - obj-$(CONFIG_VMD) += vmd.o -+obj-$(CONFIG_PCIE_MTK) += pcie-mediatek.o ---- /dev/null -+++ b/drivers/pci/host/pcie-mediatek.c -@@ -0,0 +1,641 @@ -+/* -+ * Mediatek MT2701/MT7623 SoC PCIE support -+ * -+ * Copyright (C) 2015 Mediatek -+ * Copyright (C) 2015 Ziv Huang <ziv.huang@mediatek.com> -+ * Copyright (C) 2015 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. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/pci.h> -+#include <linux/ioport.h> -+#include <linux/interrupt.h> -+#include <linux/spinlock.h> -+#include <linux/init.h> -+#include <linux/device.h> -+#include <linux/io.h> -+#include <linux/delay.h> -+#include <asm/irq.h> -+#include <asm/mach/pci.h> -+#include <linux/module.h> -+#include <linux/of.h> -+#include <linux/of_address.h> -+#include <linux/of_pci.h> -+#include <linux/of_platform.h> -+#include <linux/of_irq.h> -+#include <linux/reset.h> -+#include <linux/platform_device.h> -+#include <linux/regulator/consumer.h> -+#include <linux/pm_runtime.h> -+#include <linux/clk.h> -+#include <linux/regmap.h> -+#include <linux/mfd/syscon.h> -+ -+#define MEMORY_BASE 0x80000000 -+ -+/* PCIE Registers */ -+#define PCICFG 0x00 -+#define PCIINT 0x08 -+#define PCIENA 0x0c -+#define CFGADDR 0x20 -+#define CFGDATA 0x24 -+#define MEMBASE 0x28 -+#define IOBASE 0x2c -+ -+/* per Port Registers */ -+#define BAR0SETUP 0x10 -+#define IMBASEBAR0 0x18 -+#define PCIE_CLASS 0x34 -+#define PCIE_SISTAT 0x50 -+ -+#define MTK_PCIE_HIGH_PERF BIT(14) -+#define PCIEP0_BASE 0x2000 -+#define PCIEP1_BASE 0x3000 -+#define PCIEP2_BASE 0x4000 -+ -+#define PHY_P0_CTL 0x9000 -+#define PHY_P1_CTL 0xa000 -+#define PHY_P2_CTL 0x4000 -+ -+#define RSTCTL_PCIE0_RST BIT(24) -+#define RSTCTL_PCIE1_RST BIT(25) -+#define RSTCTL_PCIE2_RST BIT(26) -+ -+#define HIFSYS_SYSCFG1 0x14 -+#define HIFSYS_SYSCFG1_PHY2_MASK (0x3 << 20) -+ -+#define MTK_PHY_CLK 0xb00 -+#define MTK_PHY_CLKDRV_OFFSET BIT(2) -+#define MTK_PHY_CLKDRV_OFFSET_MASK 0xe -+#define MTK_PHY_PLL 0xb04 -+#define MTK_PHY_CLKDRV_AMP BIT(30) -+#define MTK_PHY_CLKDRV_AMP_MASK 0xe0000000 -+#define MTK_PHY_REFCLK_SEL 0xc00 -+#define MTK_PHY_XTAL_EXT_EN (BIT(17) | BIT(12)) -+#define MTK_PHY_XTAL_EXT_EN_MASK 0x33000 -+#define MTK_PHY_PLL_BC 0xc08 -+#define MTK_PHY_PLL_BC_PE2H 0xc0 -+#define MTK_PHY_PLL_BC_PE2H_MASK 0x380000 -+#define MTK_PHY_PLL_IC 0xc0c -+#define MTK_PHY_PLL_IC_BR_PE2H BIT(28) -+#define MTK_PHY_PLL_IC_BR_PE2H_MASK 0x30000000 -+#define MTK_PHY_PLL_IC_PE2H BIT(12) -+#define MTK_PHY_PLL_IC_PE2H_MASK 0xf000 -+#define MTK_PHY_PLL_IR 0xc10 -+#define MTK_PHY_PLL_IR_PE2H BIT(17) -+#define MTK_PHY_PLL_IR_PE2H_MASK 0xf0000 -+#define MTK_PHY_PLL_BP 0xc14 -+#define MTK_PHY_PLL_BP_PE2H (BIT(19) | BIT(17)) -+#define MTK_PHY_PLL_BP_PE2H_MASK 0xf0000 -+#define MTK_PHY_SSC_DELTA1 0xc3c -+#define MTK_PHY_SSC_DELTA1_PE2H (0x3c << 16) -+#define MTK_PHY_SSC_DELTA1_PE2H_MASK 0xffff0000 -+#define MTK_PHY_SSC_DELTA 0xc48 -+#define MTK_PHY_SSC_DELTA_PE2H 0x36 -+#define MTK_PHY_SSC_DELTA_PE2H_MASK 0xffff -+ -+#define MAX_PORT_NUM 3 -+ -+struct mtk_pcie_port { -+ int id; -+ int enable; -+ int irq; -+ u32 link; -+ void __iomem *phy_base; -+ struct reset_control *rstc; -+}; -+ -+#define mtk_foreach_port(pcie, p) \ -+ for ((p) = pcie->port; \ -+ (p) != &pcie->port[MAX_PORT_NUM]; (p)++) -+ -+struct mtk_pcie { -+ struct device *dev; -+ void __iomem *pcie_base; -+ struct regmap *hifsys; -+ -+ struct resource io; -+ struct resource pio; -+ struct resource mem; -+ struct resource prefetch; -+ struct resource busn; -+ -+ u32 io_bus_addr; -+ u32 mem_bus_addr; -+ -+ struct clk *clk; -+ -+ struct mtk_pcie_port port[MAX_PORT_NUM]; -+ int pcie_card_link; -+}; -+ -+static struct mtk_pcie_port_data { -+ u32 base; -+ u32 perst_n; -+ u32 interrupt_en; -+} mtk_pcie_port_data[MAX_PORT_NUM] = { -+ { PCIEP0_BASE, BIT(1), BIT(20) }, -+ { PCIEP1_BASE, BIT(2), BIT(21) }, -+ { PCIEP2_BASE, BIT(3), BIT(22) }, -+}; -+ -+static const struct mtk_phy_init { -+ uint32_t reg; -+ uint32_t mask; -+ uint32_t val; -+} mtk_phy_init[] = { -+ { MTK_PHY_REFCLK_SEL, MTK_PHY_XTAL_EXT_EN_MASK, MTK_PHY_XTAL_EXT_EN }, -+ { MTK_PHY_PLL, MTK_PHY_CLKDRV_AMP_MASK, MTK_PHY_CLKDRV_AMP }, -+ { MTK_PHY_CLK, MTK_PHY_CLKDRV_OFFSET_MASK, MTK_PHY_CLKDRV_OFFSET }, -+ { MTK_PHY_SSC_DELTA1, MTK_PHY_SSC_DELTA1_PE2H_MASK, MTK_PHY_SSC_DELTA1_PE2H }, -+ { MTK_PHY_SSC_DELTA, MTK_PHY_SSC_DELTA_PE2H_MASK, MTK_PHY_SSC_DELTA_PE2H }, -+ { MTK_PHY_PLL_IC, MTK_PHY_PLL_IC_BR_PE2H_MASK, MTK_PHY_PLL_IC_BR_PE2H }, -+ { MTK_PHY_PLL_BC, MTK_PHY_PLL_BC_PE2H_MASK, MTK_PHY_PLL_BC_PE2H }, -+ { MTK_PHY_PLL_IR, MTK_PHY_PLL_IR_PE2H_MASK, MTK_PHY_PLL_IR_PE2H }, -+ { MTK_PHY_PLL_IC, MTK_PHY_PLL_IC_PE2H_MASK, MTK_PHY_PLL_IC_PE2H }, -+ { MTK_PHY_PLL_BP, MTK_PHY_PLL_BP_PE2H_MASK, MTK_PHY_PLL_BP_PE2H }, -+}; -+ -+static struct mtk_pcie *sys_to_pcie(struct pci_sys_data *sys) -+{ -+ return sys->private_data; -+} -+ -+static void pcie_w32(struct mtk_pcie *pcie, u32 val, unsigned reg) -+{ -+ iowrite32(val, pcie->pcie_base + reg); -+} -+ -+static u32 pcie_r32(struct mtk_pcie *pcie, unsigned reg) -+{ -+ return ioread32(pcie->pcie_base + reg); -+} -+ -+static void pcie_m32(struct mtk_pcie *pcie, u32 mask, u32 val, unsigned reg) -+{ -+ u32 v = pcie_r32(pcie, reg); -+ -+ v &= mask; -+ v |= val; -+ pcie_w32(pcie, v, reg); -+} -+ -+static int pcie_config_read(struct pci_bus *bus, unsigned int devfn, int where, -+ int size, u32 *val) -+{ -+ struct mtk_pcie *pcie = sys_to_pcie(bus->sysdata); -+ unsigned int slot = PCI_SLOT(devfn); -+ u8 func = PCI_FUNC(devfn); -+ u32 address; -+ u32 data; -+ u32 num = 0; -+ -+ if (bus) -+ num = bus->number; -+ -+ address = (((where & 0xf00) >> 8) << 24) | -+ (num << 16) | -+ (slot << 11) | -+ (func << 8) | -+ (where & 0xfc); -+ -+ pcie_w32(pcie, address, CFGADDR); -+ data = pcie_r32(pcie, CFGDATA); -+ -+ switch (size) { -+ case 1: -+ *val = (data >> ((where & 3) << 3)) & 0xff; -+ break; -+ case 2: -+ *val = (data >> ((where & 3) << 3)) & 0xffff; -+ break; -+ case 4: -+ *val = data; -+ break; -+ } -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static int pcie_config_write(struct pci_bus *bus, unsigned int devfn, int where, -+ int size, u32 val) -+{ -+ struct mtk_pcie *pcie = sys_to_pcie(bus->sysdata); -+ unsigned int slot = PCI_SLOT(devfn); -+ u8 func = PCI_FUNC(devfn); -+ u32 address; -+ u32 data; -+ u32 num = 0; -+ -+ if (bus) -+ num = bus->number; -+ -+ address = (((where & 0xf00) >> 8) << 24) | -+ (num << 16) | (slot << 11) | (func << 8) | (where & 0xfc); -+ pcie_w32(pcie, address, CFGADDR); -+ data = pcie_r32(pcie, CFGDATA); -+ -+ switch (size) { -+ case 1: -+ data = (data & ~(0xff << ((where & 3) << 3))) | -+ (val << ((where & 3) << 3)); -+ break; -+ case 2: -+ data = (data & ~(0xffff << ((where & 3) << 3))) | -+ (val << ((where & 3) << 3)); -+ break; -+ case 4: -+ data = val; -+ break; -+ } -+ pcie_w32(pcie, data, CFGDATA); -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static struct pci_ops mtk_pcie_ops = { -+ .read = pcie_config_read, -+ .write = pcie_config_write, -+}; -+ -+static int __init mtk_pcie_setup(int nr, struct pci_sys_data *sys) -+{ -+ struct mtk_pcie *pcie = sys_to_pcie(sys); -+ -+ request_resource(&ioport_resource, &pcie->pio); -+ request_resource(&iomem_resource, &pcie->mem); -+ -+ pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); -+ pci_add_resource_offset(&sys->resources, &pcie->pio, sys->io_offset); -+ pci_add_resource(&sys->resources, &pcie->busn); -+ -+ return 1; -+} -+ -+static struct pci_bus * __init mtk_pcie_scan_bus(int nr, -+ struct pci_sys_data *sys) -+{ -+ struct mtk_pcie *pcie = sys_to_pcie(sys); -+ struct pci_bus *bus; -+ -+ bus = pci_create_root_bus(pcie->dev, sys->busnr, &mtk_pcie_ops, sys, -+ &sys->resources); -+ if (!bus) -+ return NULL; -+ -+ pci_scan_child_bus(bus); -+ -+ return bus; -+} -+ -+static int __init mtk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ struct mtk_pcie *pcie = sys_to_pcie(dev->bus->sysdata); -+ struct mtk_pcie_port *port; -+ int irq = -1; -+ -+ mtk_foreach_port(pcie, port) -+ if (port->id == slot) -+ irq = port->irq; -+ -+ return irq; -+} -+ -+static void mtk_pcie_configure_phy(struct mtk_pcie *pcie, -+ struct mtk_pcie_port *port) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(mtk_phy_init); i++) { -+ void __iomem *phy_addr = port->phy_base + mtk_phy_init[i].reg; -+ u32 val = ioread32(phy_addr); -+ -+ val &= ~mtk_phy_init[i].mask; -+ val |= mtk_phy_init[i].val; -+ iowrite32(val, phy_addr); -+ } -+ usleep_range(5000, 6000); -+} -+ -+static void mtk_pcie_configure_rc(struct mtk_pcie *pcie, -+ struct mtk_pcie_port *port, -+ struct pci_bus *bus) -+{ -+ u32 val = 0; -+ -+ pcie_config_write(bus, -+ port->id << 3, -+ PCI_BASE_ADDRESS_0, 4, MEMORY_BASE); -+ -+ pcie_config_read(bus, -+ port->id << 3, PCI_BASE_ADDRESS_0, 4, &val); -+ -+ /* Configure RC Credit */ -+ pcie_config_read(bus, port->id << 3, 0x73c, 4, &val); -+ val &= ~(0x9fff) << 16; -+ val |= 0x806c << 16; -+ pcie_config_write(bus, port->id << 3, 0x73c, 4, val); -+ -+ /* Configure RC FTS number */ -+ pcie_config_read(bus, port->id << 3, 0x70c, 4, &val); -+ val &= ~(0xff3) << 8; -+ val |= 0x50 << 8; -+ pcie_config_write(bus, port->id << 3, 0x70c, 4, val); -+} -+ -+static int mtk_pcie_preinit(struct mtk_pcie *pcie) -+{ -+ struct mtk_pcie_port *port; -+ u32 val = 0; -+ struct pci_bus bus; -+ struct pci_sys_data sys; -+ -+ memset(&bus, 0, sizeof(bus)); -+ memset(&sys, 0, sizeof(sys)); -+ bus.sysdata = (void *)&sys; -+ sys.private_data = (void *)pcie; -+ -+ pcibios_min_io = 0; -+ pcibios_min_mem = 0; -+ -+ /* The PHY on Port 2 is shared with USB */ -+ if (pcie->port[2].enable) -+ regmap_update_bits(pcie->hifsys, HIFSYS_SYSCFG1, -+ HIFSYS_SYSCFG1_PHY2_MASK, 0x0); -+ -+ /* PCIe RC Reset */ -+ mtk_foreach_port(pcie, port) -+ if (port->enable) -+ reset_control_assert(port->rstc); -+ usleep_range(1000, 2000); -+ mtk_foreach_port(pcie, port) -+ if (port->enable) -+ reset_control_deassert(port->rstc); -+ usleep_range(1000, 2000); -+ -+ /* Configure PCIe PHY */ -+ mtk_foreach_port(pcie, port) -+ if (port->enable) -+ mtk_pcie_configure_phy(pcie, port); -+ -+ /* PCIe EP reset */ -+ val = 0; -+ mtk_foreach_port(pcie, port) -+ if (port->enable) -+ val |= mtk_pcie_port_data[port->id].perst_n; -+ pcie_w32(pcie, pcie_r32(pcie, PCICFG) | val, PCICFG); -+ usleep_range(1000, 2000); -+ pcie_w32(pcie, pcie_r32(pcie, PCICFG) & ~val, PCICFG); -+ usleep_range(1000, 2000); -+ msleep(100); -+ -+ /* check the link status */ -+ val = 0; -+ mtk_foreach_port(pcie, port) { -+ if (port->enable) { -+ u32 base = mtk_pcie_port_data[port->id].base; -+ -+ if ((pcie_r32(pcie, base + PCIE_SISTAT) & 0x1)) -+ port->link = 1; -+ else -+ reset_control_assert(port->rstc); -+ } -+ } -+ -+ mtk_foreach_port(pcie, port) -+ if (port->link) -+ pcie->pcie_card_link++; -+ -+ if (!pcie->pcie_card_link) -+ return -ENODEV; -+ -+ pcie_w32(pcie, pcie->mem_bus_addr, MEMBASE); -+ pcie_w32(pcie, pcie->io_bus_addr, IOBASE); -+ -+ mtk_foreach_port(pcie, port) { -+ if (port->link) { -+ u32 base = mtk_pcie_port_data[port->id].base; -+ u32 inte = mtk_pcie_port_data[port->id].interrupt_en; -+ -+ pcie_m32(pcie, 0, inte, PCIENA); -+ pcie_w32(pcie, 0x7fff0001, base + BAR0SETUP); -+ pcie_w32(pcie, MEMORY_BASE, base + IMBASEBAR0); -+ pcie_w32(pcie, 0x06040001, base + PCIE_CLASS); -+ } -+ } -+ -+ mtk_foreach_port(pcie, port) -+ if (port->link) -+ mtk_pcie_configure_rc(pcie, port, &bus); -+ -+ return 0; -+} -+ -+static int mtk_pcie_parse_dt(struct mtk_pcie *pcie) -+{ -+ struct device_node *np = pcie->dev->of_node, *port; -+ struct of_pci_range_parser parser; -+ struct of_pci_range range; -+ struct resource res; -+ int err; -+ -+ pcie->hifsys = syscon_regmap_lookup_by_phandle(np, "mediatek,hifsys"); -+ if (IS_ERR(pcie->hifsys)) { -+ dev_err(pcie->dev, "missing \"mediatek,hifsys\" phandle\n"); -+ return PTR_ERR(pcie->hifsys); -+ } -+ -+ if (of_pci_range_parser_init(&parser, np)) { -+ dev_err(pcie->dev, "missing \"ranges\" property\n"); -+ return -EINVAL; -+ } -+ -+ for_each_of_pci_range(&parser, &range) { -+ err = of_pci_range_to_resource(&range, np, &res); -+ if (err < 0) { -+ dev_err(pcie->dev, "failed to read resource range\n"); -+ return err; -+ } -+ -+ switch (res.flags & IORESOURCE_TYPE_BITS) { -+ case IORESOURCE_IO: -+ memcpy(&pcie->pio, &res, sizeof(res)); -+ pcie->pio.start = (resource_size_t)range.pci_addr; -+ pcie->pio.end = (resource_size_t) -+ (range.pci_addr + range.size - 1); -+ pcie->io_bus_addr = (resource_size_t)range.cpu_addr; -+ break; -+ -+ case IORESOURCE_MEM: -+ if (res.flags & IORESOURCE_PREFETCH) { -+ memcpy(&pcie->prefetch, &res, sizeof(res)); -+ pcie->prefetch.name = "prefetchable"; -+ pcie->prefetch.start = -+ (resource_size_t)range.pci_addr; -+ pcie->prefetch.end = (resource_size_t) -+ (range.pci_addr + range.size - 1); -+ } else { -+ memcpy(&pcie->mem, &res, sizeof(res)); -+ pcie->mem.name = "non-prefetchable"; -+ pcie->mem.start = (resource_size_t) -+ range.pci_addr; -+ pcie->prefetch.end = (resource_size_t) -+ (range.pci_addr + range.size - 1); -+ pcie->mem_bus_addr = (resource_size_t) -+ range.cpu_addr; -+ } -+ break; -+ } -+ } -+ -+ err = of_pci_parse_bus_range(np, &pcie->busn); -+ if (err < 0) { -+ dev_err(pcie->dev, "failed to parse ranges property: %d\n", -+ err); -+ pcie->busn.name = np->name; -+ pcie->busn.start = 0; -+ pcie->busn.end = 0xff; -+ pcie->busn.flags = IORESOURCE_BUS; -+ } -+ -+ /* parse root ports */ -+ for_each_child_of_node(np, port) { -+ unsigned int index; -+ char rst[] = "pcie0"; -+ -+ err = of_pci_get_devfn(port); -+ if (err < 0) { -+ dev_err(pcie->dev, "failed to parse address: %d\n", -+ err); -+ return err; -+ } -+ -+ index = PCI_SLOT(err); -+ if (index > MAX_PORT_NUM) { -+ dev_err(pcie->dev, "invalid port number: %d\n", index); -+ continue; -+ } -+ index--; -+ pcie->port[index].id = index; -+ -+ if (!of_device_is_available(port)) -+ continue; -+ -+ rst[4] += index; -+ pcie->port[index].rstc = devm_reset_control_get(pcie->dev, -+ rst); -+ if (!IS_ERR(pcie->port[index].rstc)) -+ pcie->port[index].enable = 1; -+ } -+ return 0; -+} -+ -+static int mtk_pcie_get_resources(struct mtk_pcie *pcie) -+{ -+ struct platform_device *pdev = to_platform_device(pcie->dev); -+ struct mtk_pcie_port *port; -+ struct resource *res; -+ -+ pcie->clk = devm_clk_get(&pdev->dev, "pcie"); -+ if (IS_ERR(pcie->clk)) { -+ dev_err(&pdev->dev, "Failed to get pcie clk\n"); -+ return PTR_ERR(pcie->clk); -+ } -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ pcie->pcie_base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(pcie->pcie_base)) { -+ dev_err(&pdev->dev, "Failed to get pcie range\n"); -+ return PTR_ERR(pcie->pcie_base); -+ } -+ -+ mtk_foreach_port(pcie, port) { -+ if (!port->enable) -+ continue; -+ res = platform_get_resource(pdev, IORESOURCE_MEM, port->id + 1); -+ port->phy_base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(port->phy_base)) { -+ dev_err(&pdev->dev, "Failed to get pcie phy%d range %p\n", -+ port->id, port->phy_base); -+ return PTR_ERR(port->phy_base); -+ } -+ port->irq = platform_get_irq(pdev, port->id); -+ } -+ -+ return clk_prepare_enable(pcie->clk); -+} -+ -+static int mtk_pcie_probe(struct platform_device *pdev) -+{ -+ struct mtk_pcie *pcie; -+ struct hw_pci hw; -+ int ret; -+ -+ pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); -+ if (!pcie) -+ return -ENOMEM; -+ -+ pcie->dev = &pdev->dev; -+ ret = mtk_pcie_parse_dt(pcie); -+ if (ret < 0) -+ return ret; -+ -+ pm_runtime_enable(&pdev->dev); -+ pm_runtime_get_sync(&pdev->dev); -+ -+ ret = mtk_pcie_get_resources(pcie); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "failed to request resources: %d\n", ret); -+ goto err_out; -+ } -+ -+ ret = mtk_pcie_preinit(pcie); -+ if (ret) -+ return ret; -+ -+ memset(&hw, 0, sizeof(hw)); -+ hw.nr_controllers = 1; -+ hw.private_data = (void **)&pcie; -+ hw.setup = mtk_pcie_setup; -+ hw.map_irq = mtk_pcie_map_irq; -+ hw.scan = mtk_pcie_scan_bus; -+ -+ pci_common_init_dev(pcie->dev, &hw); -+ platform_set_drvdata(pdev, pcie); -+ -+ return 0; -+ -+err_out: -+ clk_disable_unprepare(pcie->clk); -+ pm_runtime_put_sync(&pdev->dev); -+ pm_runtime_disable(&pdev->dev); -+ -+ return ret; -+} -+ -+static const struct of_device_id mtk_pcie_ids[] = { -+ { .compatible = "mediatek,mt2701-pcie" }, -+ { .compatible = "mediatek,mt7623-pcie" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mtk_pcie_ids); -+ -+static struct platform_driver mtk_pcie_driver = { -+ .probe = mtk_pcie_probe, -+ .driver = { -+ .name = "mediatek-pcie", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(mtk_pcie_ids), -+ }, -+}; -+ -+static int __init mtk_pcie_init(void) -+{ -+ return platform_driver_register(&mtk_pcie_driver); -+} -+ -+module_init(mtk_pcie_init); diff --git a/target/linux/mediatek/patches-4.9/0004-soc-mediatek-Add-MT2701-power-dt-bindings.patch b/target/linux/mediatek/patches-4.9/0004-soc-mediatek-Add-MT2701-power-dt-bindings.patch deleted file mode 100644 index 8d91b12..0000000 --- a/target/linux/mediatek/patches-4.9/0004-soc-mediatek-Add-MT2701-power-dt-bindings.patch +++ /dev/null @@ -1,75 +0,0 @@ -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 04/57] soc: mediatek: Add MT2701 power dt-bindings - -Add power dt-bindings for MT2701. - -Signed-off-by: Shunli Wang <shunli.wang@mediatek.com> -Signed-off-by: James Liao <jamesjj.liao@mediatek.com> -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 | 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 -+++ b/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt -@@ -9,17 +9,20 @@ domain control. - - The driver implements the Generic PM domain bindings described in - power/power_domain.txt. It provides the power domains defined in --include/dt-bindings/power/mt8173-power.h. -+include/dt-bindings/power/mt8173-power.h and mt2701-power.h. - - Required properties: --- compatible: Must be "mediatek,mt8173-scpsys" -+- compatible: Should be one of: -+ - "mediatek,mt2701-scpsys" -+ - "mediatek,mt8173-scpsys" - - #power-domain-cells: Must be 1 - - reg: Address range of the SCPSYS unit - - infracfg: must contain a phandle to the infracfg controller - - clock, clock-names: clocks according to the common clock binding. -- The clocks needed "mm", "mfg", "venc" and "venc_lt". -- These are the clocks which hardware needs to be enabled -- before enabling certain power domains. -+ These are clocks which hardware needs to be -+ enabled before enabling certain power domains. -+ Required clocks for MT2701: "mm", "mfg", "ethif" -+ Required clocks for MT8173: "mm", "mfg", "venc", "venc_lt" - - Optional properties: - - vdec-supply: Power supply for the vdec power domain ---- /dev/null -+++ b/include/dt-bindings/power/mt2701-power.h -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2015 MediaTek Inc. -+ * -+ * 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. -+ */ -+ -+#ifndef _DT_BINDINGS_POWER_MT2701_POWER_H -+#define _DT_BINDINGS_POWER_MT2701_POWER_H -+ -+#define MT2701_POWER_DOMAIN_CONN 0 -+#define MT2701_POWER_DOMAIN_DISP 1 -+#define MT2701_POWER_DOMAIN_IFR_MSC 2 -+#define MT2701_POWER_DOMAIN_VDEC 3 -+#define MT2701_POWER_DOMAIN_ISP 4 -+#define MT2701_POWER_DOMAIN_BDP 5 -+#define MT2701_POWER_DOMAIN_ETH 6 -+#define MT2701_POWER_DOMAIN_HIF 7 -+ -+#endif /* _DT_BINDINGS_POWER_MT2701_POWER_H */ diff --git a/target/linux/mediatek/patches-4.9/0005-clk-mediatek-Add-MT2701-clock-support.patch b/target/linux/mediatek/patches-4.9/0005-clk-mediatek-Add-MT2701-clock-support.patch deleted file mode 100644 index ef40ba2..0000000 --- a/target/linux/mediatek/patches-4.9/0005-clk-mediatek-Add-MT2701-clock-support.patch +++ /dev/null @@ -1,1431 +0,0 @@ -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 05/57] clk: mediatek: Add MT2701 clock support - -Add MT2701 clock support, include topckgen, apmixedsys, -infracfg, pericfg and subsystem clocks. - -Signed-off-by: Shunli Wang <shunli.wang@mediatek.com> -Signed-off-by: James Liao <jamesjj.liao@mediatek.com> ---- - drivers/clk/mediatek/Kconfig | 8 + - drivers/clk/mediatek/Makefile | 1 + - drivers/clk/mediatek/clk-gate.c | 56 ++ - drivers/clk/mediatek/clk-gate.h | 2 + - drivers/clk/mediatek/clk-mt2701.c | 1210 +++++++++++++++++++++++++++++++++++++ - drivers/clk/mediatek/clk-mtk.c | 25 + - drivers/clk/mediatek/clk-mtk.h | 35 +- - 7 files changed, 1334 insertions(+), 3 deletions(-) - create mode 100644 drivers/clk/mediatek/clk-mt2701.c - ---- a/drivers/clk/mediatek/Kconfig -+++ b/drivers/clk/mediatek/Kconfig -@@ -6,6 +6,14 @@ config COMMON_CLK_MEDIATEK - ---help--- - Mediatek SoCs' clock support. - -+config COMMON_CLK_MT2701 -+ bool "Clock driver for Mediatek MT2701 and MT7623" -+ depends on COMMON_CLK -+ select COMMON_CLK_MEDIATEK -+ default ARCH_MEDIATEK -+ ---help--- -+ This driver supports Mediatek MT2701 and MT7623 clocks. -+ - config COMMON_CLK_MT8135 - bool "Clock driver for Mediatek MT8135" - depends on ARCH_MEDIATEK || COMPILE_TEST ---- a/drivers/clk/mediatek/Makefile -+++ b/drivers/clk/mediatek/Makefile -@@ -1,4 +1,5 @@ - obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o - obj-$(CONFIG_RESET_CONTROLLER) += reset.o -+obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o - obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o - obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o ---- a/drivers/clk/mediatek/clk-gate.c -+++ b/drivers/clk/mediatek/clk-gate.c -@@ -61,6 +61,26 @@ static void mtk_cg_clr_bit(struct clk_hw - regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit)); - } - -+static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw) -+{ -+ struct mtk_clk_gate *cg = to_mtk_clk_gate(hw); -+ u32 val; -+ -+ regmap_read(cg->regmap, cg->sta_ofs, &val); -+ val |= BIT(cg->bit); -+ regmap_write(cg->regmap, cg->sta_ofs, val); -+} -+ -+static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw) -+{ -+ struct mtk_clk_gate *cg = to_mtk_clk_gate(hw); -+ u32 val; -+ -+ regmap_read(cg->regmap, cg->sta_ofs, &val); -+ val &= ~(BIT(cg->bit)); -+ regmap_write(cg->regmap, cg->sta_ofs, val); -+} -+ - static int mtk_cg_enable(struct clk_hw *hw) - { - mtk_cg_clr_bit(hw); -@@ -85,6 +105,30 @@ static void mtk_cg_disable_inv(struct cl - mtk_cg_clr_bit(hw); - } - -+static int mtk_cg_enable_no_setclr(struct clk_hw *hw) -+{ -+ mtk_cg_clr_bit_no_setclr(hw); -+ -+ return 0; -+} -+ -+static void mtk_cg_disable_no_setclr(struct clk_hw *hw) -+{ -+ mtk_cg_set_bit_no_setclr(hw); -+} -+ -+static int mtk_cg_enable_inv_no_setclr(struct clk_hw *hw) -+{ -+ mtk_cg_set_bit_no_setclr(hw); -+ -+ return 0; -+} -+ -+static void mtk_cg_disable_inv_no_setclr(struct clk_hw *hw) -+{ -+ mtk_cg_clr_bit_no_setclr(hw); -+} -+ - const struct clk_ops mtk_clk_gate_ops_setclr = { - .is_enabled = mtk_cg_bit_is_cleared, - .enable = mtk_cg_enable, -@@ -97,6 +141,18 @@ const struct clk_ops mtk_clk_gate_ops_se - .disable = mtk_cg_disable_inv, - }; - -+const struct clk_ops mtk_clk_gate_ops_no_setclr = { -+ .is_enabled = mtk_cg_bit_is_cleared, -+ .enable = mtk_cg_enable_no_setclr, -+ .disable = mtk_cg_disable_no_setclr, -+}; -+ -+const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = { -+ .is_enabled = mtk_cg_bit_is_set, -+ .enable = mtk_cg_enable_inv_no_setclr, -+ .disable = mtk_cg_disable_inv_no_setclr, -+}; -+ - struct clk *mtk_clk_register_gate( - const char *name, - const char *parent_name, ---- a/drivers/clk/mediatek/clk-gate.h -+++ b/drivers/clk/mediatek/clk-gate.h -@@ -36,6 +36,8 @@ static inline struct mtk_clk_gate *to_mt - - extern const struct clk_ops mtk_clk_gate_ops_setclr; - extern const struct clk_ops mtk_clk_gate_ops_setclr_inv; -+extern const struct clk_ops mtk_clk_gate_ops_no_setclr; -+extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv; - - struct clk *mtk_clk_register_gate( - const char *name, ---- /dev/null -+++ b/drivers/clk/mediatek/clk-mt2701.c -@@ -0,0 +1,1210 @@ -+/* -+ * Copyright (c) 2014 MediaTek Inc. -+ * Author: Shunli Wang <shunli.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 version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include <linux/clk.h> -+#include <linux/of.h> -+#include <linux/of_address.h> -+ -+#include "clk-mtk.h" -+#include "clk-gate.h" -+ -+#include <dt-bindings/clock/mt2701-clk.h> -+ -+static DEFINE_SPINLOCK(lock); -+ -+static const struct mtk_fixed_clk top_fixed_clks[] __initconst = { -+ FIXED_CLK(CLK_TOP_DPI, "dpi_ck", "clk26m", 108 * MHZ), -+ FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", "clk26m", 400 * MHZ), -+ FIXED_CLK(CLK_TOP_VENCPLL, "vencpll_ck", "clk26m", 295750000), -+ FIXED_CLK(CLK_TOP_HDMI_0_PIX340M, "hdmi_0_pix340m", "clk26m", 340 * MHZ), -+ FIXED_CLK(CLK_TOP_HDMI_0_DEEP340M, "hdmi_0_deep340m", "clk26m", 340 * MHZ), -+ FIXED_CLK(CLK_TOP_HDMI_0_PLL340M, "hdmi_0_pll340m", "clk26m", 340 * MHZ), -+ FIXED_CLK(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_dig_cts", "clk26m", 300 * MHZ), -+ FIXED_CLK(CLK_TOP_HADDS2_FB, "hadds2_fbclk", "clk26m", 27 * MHZ), -+ FIXED_CLK(CLK_TOP_WBG_DIG_416M, "wbg_dig_ck_416m", "clk26m", 416 * MHZ), -+}; -+ -+static const struct mtk_fixed_factor top_fixed_divs[] __initconst = { -+ FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, 1), -+ FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2), -+ FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3), -+ FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5), -+ FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7), -+ FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2), -+ FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4), -+ FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8), -+ FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16), -+ FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2), -+ FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4), -+ FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8), -+ FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2), -+ FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4), -+ FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2), -+ FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4), -+ -+ FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1, 1), -+ FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), -+ FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), -+ FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), -+ FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), -+ FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26), -+ FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll", 1, 52), -+ FACTOR(CLK_TOP_UNIVPLL_D108, "univpll_d108", "univpll", 1, 108), -+ FACTOR(CLK_TOP_USB_PHY48M, "USB_PHY48M_CK", "univpll", 1, 26), -+ FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2), -+ FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4), -+ FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8), -+ FACTOR(CLK_TOP_8BDAC, "8bdac_ck", "univpll_d2", 1, 1), -+ FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, 2), -+ FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, 4), -+ FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, 8), -+ FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll_d3", 1, 16), -+ FACTOR(CLK_TOP_UNIVPLL2_D32, "univpll2_d32", "univpll_d3", 1, 32), -+ FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2), -+ FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4), -+ FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8), -+ -+ FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1), -+ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2), -+ FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4), -+ FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, 8), -+ -+ FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1), -+ FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), -+ -+ FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "dmpll_ck", 1, 2), -+ FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "dmpll_ck", 1, 4), -+ FACTOR(CLK_TOP_DMPLL_X2, "dmpll_x2", "dmpll_ck", 1, 1), -+ -+ FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, 1), -+ FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2), -+ FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4), -+ -+ FACTOR(CLK_TOP_VDECPLL, "vdecpll_ck", "vdecpll", 1, 1), -+ FACTOR(CLK_TOP_TVD2PLL, "tvd2pll_ck", "tvd2pll", 1, 1), -+ FACTOR(CLK_TOP_TVD2PLL_D2, "tvd2pll_d2", "tvd2pll", 1, 2), -+ -+ FACTOR(CLK_TOP_MIPIPLL, "mipipll", "dpi_ck", 1, 1), -+ FACTOR(CLK_TOP_MIPIPLL_D2, "mipipll_d2", "dpi_ck", 1, 2), -+ FACTOR(CLK_TOP_MIPIPLL_D4, "mipipll_d4", "dpi_ck", 1, 4), -+ -+ FACTOR(CLK_TOP_HDMIPLL, "hdmipll_ck", "hdmitx_dig_cts", 1, 1), -+ FACTOR(CLK_TOP_HDMIPLL_D2, "hdmipll_d2", "hdmitx_dig_cts", 1, 2), -+ FACTOR(CLK_TOP_HDMIPLL_D3, "hdmipll_d3", "hdmitx_dig_cts", 1, 3), -+ -+ FACTOR(CLK_TOP_ARMPLL_1P3G, "armpll_1p3g_ck", "armpll", 1, 1), -+ -+ FACTOR(CLK_TOP_AUDPLL, "audpll", "audpll_sel", 1, 1), -+ FACTOR(CLK_TOP_AUDPLL_D4, "audpll_d4", "audpll_sel", 1, 4), -+ FACTOR(CLK_TOP_AUDPLL_D8, "audpll_d8", "audpll_sel", 1, 8), -+ FACTOR(CLK_TOP_AUDPLL_D16, "audpll_d16", "audpll_sel", 1, 16), -+ FACTOR(CLK_TOP_AUDPLL_D24, "audpll_d24", "audpll_sel", 1, 24), -+ -+ FACTOR(CLK_TOP_AUD1PLL_98M, "aud1pll_98m_ck", "aud1pll", 1, 3), -+ FACTOR(CLK_TOP_AUD2PLL_90M, "aud2pll_90m_ck", "aud2pll", 1, 3), -+ FACTOR(CLK_TOP_HADDS2PLL_98M, "hadds2pll_98m", "hadds2pll", 1, 3), -+ FACTOR(CLK_TOP_HADDS2PLL_294M, "hadds2pll_294m", "hadds2pll", 1, 1), -+ FACTOR(CLK_TOP_ETHPLL_500M, "ethpll_500m_ck", "ethpll", 1, 1), -+ FACTOR(CLK_TOP_CLK26M_D8, "clk26m_d8", "clk26m", 1, 8), -+ FACTOR(CLK_TOP_32K_INTERNAL, "32k_internal", "clk26m", 1, 793), -+ FACTOR(CLK_TOP_32K_EXTERNAL, "32k_external", "rtc32k", 1, 1), -+}; -+ -+static const char * const axi_parents[] __initconst = { -+ "clk26m", -+ "syspll1_d2", -+ "syspll_d5", -+ "syspll1_d4", -+ "univpll_d5", -+ "univpll2_d2", -+ "mmpll_d2", -+ "dmpll_d2" -+}; -+ -+static const char * const mem_parents[] __initconst = { -+ "clk26m", -+ "dmpll_ck" -+}; -+ -+static const char * const ddrphycfg_parents[] __initconst = { -+ "clk26m", -+ "syspll1_d8" -+}; -+ -+static const char * const mm_parents[] __initconst = { -+ "clk26m", -+ "vencpll_ck", -+ "syspll1_d2", -+ "syspll1_d4", -+ "univpll_d5", -+ "univpll1_d2", -+ "univpll2_d2", -+ "dmpll_ck" -+}; -+ -+static const char * const pwm_parents[] __initconst = { -+ "clk26m", -+ "univpll2_d4", -+ "univpll3_d2", -+ "univpll1_d4", -+}; -+ -+static const char * const vdec_parents[] __initconst = { -+ "clk26m", -+ "vdecpll_ck", -+ "syspll_d5", -+ "syspll1_d4", -+ "univpll_d5", -+ "univpll2_d2", -+ "vencpll_ck", -+ "msdcpll_d2", -+ "mmpll_d2" -+}; -+ -+static const char * const mfg_parents[] __initconst = { -+ "clk26m", -+ "mmpll_ck", -+ "dmpll_x2_ck", -+ "msdcpll_ck", -+ "clk26m", -+ "syspll_d3", -+ "univpll_d3", -+ "univpll1_d2" -+}; -+ -+static const char * const camtg_parents[] __initconst = { -+ "clk26m", -+ "univpll_d26", -+ "univpll2_d2", -+ "syspll3_d2", -+ "syspll3_d4", -+ "msdcpll_d2", -+ "mmpll_d2" -+}; -+ -+static const char * const uart_parents[] __initconst = { -+ "clk26m", -+ "univpll2_d8" -+}; -+ -+static const char * const spi_parents[] __initconst = { -+ "clk26m", -+ "syspll3_d2", -+ "syspll4_d2", -+ "univpll2_d4", -+ "univpll1_d8" -+}; -+ -+static const char * const usb20_parents[] __initconst = { -+ "clk26m", -+ "univpll1_d8", -+ "univpll3_d4" -+}; -+ -+static const char * const msdc30_parents[] __initconst = { -+ "clk26m", -+ "msdcpll_d2", -+ "syspll2_d2", -+ "syspll1_d4", -+ "univpll1_d4", -+ "univpll2_d4" -+}; -+ -+static const char * const audio_parents[] __initconst = { -+ "clk26m", -+ "syspll1_d16" -+}; -+ -+static const char * const aud_intbus_parents[] __initconst = { -+ "clk26m", -+ "syspll1_d4", -+ "syspll3_d2", -+ "syspll4_d2", -+ "univpll3_d2", -+ "univpll2_d4" -+}; -+ -+static const char * const pmicspi_parents[] __initconst = { -+ "clk26m", -+ "syspll1_d8", -+ "syspll2_d4", -+ "syspll4_d2", -+ "syspll3_d4", -+ "syspll2_d8", -+ "syspll1_d16", -+ "univpll3_d4", -+ "univpll_d26", -+ "dmpll_d2", -+ "dmpll_d4" -+}; -+ -+static const char * const scp_parents[] __initconst = { -+ "clk26m", -+ "syspll1_d8", -+ "dmpll_d2", -+ "dmpll_d4" -+}; -+ -+static const char * const dpi0_parents[] __initconst = { -+ "clk26m", -+ "mipipll", -+ "mipipll_d2", -+ "mipipll_d4", -+ "clk26m", -+ "tvdpll_ck", -+ "tvdpll_d2", -+ "tvdpll_d4" -+}; -+ -+static const char * const dpi1_parents[] __initconst = { -+ "clk26m", -+ "tvdpll_ck", -+ "tvdpll_d2", -+ "tvdpll_d4" -+}; -+ -+static const char * const tve_parents[] __initconst = { -+ "clk26m", -+ "mipipll", -+ "mipipll_d2", -+ "mipipll_d4", -+ "clk26m", -+ "tvdpll_ck", -+ "tvdpll_d2", -+ "tvdpll_d4" -+}; -+ -+static const char * const hdmi_parents[] __initconst = { -+ "clk26m", -+ "hdmipll_ck", -+ "hdmipll_d2", -+ "hdmipll_d3" -+}; -+ -+static const char * const apll_parents[] __initconst = { -+ "clk26m", -+ "audpll", -+ "audpll_d4", -+ "audpll_d8", -+ "audpll_d16", -+ "audpll_d24", -+ "clk26m", -+ "clk26m" -+}; -+ -+static const char * const rtc_parents[] __initconst = { -+ "32k_internal", -+ "32k_external", -+ "clk26m", -+ "univpll3_d8" -+}; -+ -+static const char * const nfi2x_parents[] __initconst = { -+ "clk26m", -+ "syspll2_d2", -+ "syspll_d7", -+ "univpll3_d2", -+ "syspll2_d4", -+ "univpll3_d4", -+ "syspll4_d4", -+ "clk26m" -+}; -+ -+static const char * const emmc_hclk_parents[] __initconst = { -+ "clk26m", -+ "syspll1_d2", -+ "syspll1_d4", -+ "syspll2_d2" -+}; -+ -+static const char * const flash_parents[] __initconst = { -+ "clk26m_d8", -+ "clk26m", -+ "syspll2_d8", -+ "syspll3_d4", -+ "univpll3_d4", -+ "syspll4_d2", -+ "syspll2_d4", -+ "univpll2_d4" -+}; -+ -+static const char * const di_parents[] __initconst = { -+ "clk26m", -+ "tvd2pll_ck", -+ "tvd2pll_d2", -+ "clk26m" -+}; -+ -+static const char * const nr_osd_parents[] __initconst = { -+ "clk26m", -+ "vencpll_ck", -+ "syspll1_d2", -+ "syspll1_d4", -+ "univpll_d5", -+ "univpll1_d2", -+ "univpll2_d2", -+ "dmpll_ck" -+}; -+ -+static const char * const hdmirx_bist_parents[] __initconst = { -+ "clk26m", -+ "syspll_d3", -+ "clk26m", -+ "syspll1_d16", -+ "syspll4_d2", -+ "syspll1_d4", -+ "vencpll_ck", -+ "clk26m" -+}; -+ -+static const char * const intdir_parents[] __initconst = { -+ "clk26m", -+ "mmpll_ck", -+ "syspll_d2", -+ "univpll_d2" -+}; -+ -+static const char * const asm_parents[] __initconst = { -+ "clk26m", -+ "univpll2_d4", -+ "univpll2_d2", -+ "syspll_d5" -+}; -+ -+static const char * const ms_card_parents[] __initconst = { -+ "clk26m", -+ "univpll3_d8", -+ "syspll4_d4" -+}; -+ -+static const char * const ethif_parents[] __initconst = { -+ "clk26m", -+ "syspll1_d2", -+ "syspll_d5", -+ "syspll1_d4", -+ "univpll_d5", -+ "univpll1_d2", -+ "dmpll_ck", -+ "dmpll_d2" -+}; -+ -+static const char * const hdmirx_parents[] __initconst = { -+ "clk26m", -+ "univpll_d52" -+}; -+ -+static const char * const cmsys_parents[] __initconst = { -+ "clk26m", -+ "syspll1_d2", -+ "univpll1_d2", -+ "univpll_d5", -+ "syspll_d5", -+ "syspll2_d2", -+ "syspll1_d4", -+ "syspll3_d2", -+ "syspll2_d4", -+ "syspll1_d8", -+ "clk26m", -+ "clk26m", -+ "clk26m", -+ "clk26m", -+ "clk26m" -+}; -+ -+static const char * const clk_8bdac_parents[] __initconst = { -+ "clkrtc_int", -+ "8bdac_ck_pre", -+ "clk26m", -+ "clk26m" -+}; -+ -+static const char * const aud2dvd_parents[] __initconst = { -+ "a1sys_hp_ck", -+ "a2sys_hp_ck" -+}; -+ -+static const char * const padmclk_parents[] __initconst = { -+ "clk26m", -+ "univpll_d26", -+ "univpll_d52", -+ "univpll_d108", -+ "univpll2_d8", -+ "univpll2_d16", -+ "univpll2_d32" -+}; -+ -+static const char * const aud_mux_parents[] __initconst = { -+ "clk26m", -+ "aud1pll_98m_ck", -+ "aud2pll_90m_ck", -+ "hadds2pll_98m", -+ "audio_ext1_ck", -+ "audio_ext2_ck" -+}; -+ -+static const char * const aud_src_parents[] __initconst = { -+ "aud_mux1_sel", -+ "aud_mux2_sel" -+}; -+ -+static const char * const cpu_parents[] __initconst = { -+ "clk26m", -+ "armpll", -+ "mainpll", -+ "mmpll" -+}; -+ -+static const struct mtk_composite top_muxes[] __initconst = { -+ MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, -+ 0x0040, 0, 3, INVALID_MUX_GATE_BIT), -+ MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1, 15), -+ MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x0040, 16, 1, 23), -+ MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x0040, 24, 3, 31), -+ -+ MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7), -+ MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15), -+ MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 16, 3, 23), -+ MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0050, 24, 3, 31), -+ MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 0, 1, 7), -+ -+ MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi_parents, 0x0060, 8, 3, 15), -+ MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 16, 2, 23), -+ MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, 0x0060, 24, 3, 31), -+ -+ MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, 0x0070, 0, 3, 7), -+ MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, 0x0070, 8, 3, 15), -+ MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", msdc30_parents, 0x0070, 16, 1, 23), -+ MUX_GATE(CLK_TOP_AUDINTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x0070, 24, 3, 31), -+ -+ MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0080, 0, 4, 7), -+ MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0080, 8, 2, 15), -+ MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x0080, 16, 3, 23), -+ MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0080, 24, 2, 31), -+ -+ MUX_GATE(CLK_TOP_TVE_SEL, "tve_sel", tve_parents, 0x0090, 0, 3, 7), -+ MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, 0x0090, 8, 2, 15), -+ MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0090, 16, 3, 23), -+ -+ MUX_GATE(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00A0, 0, 2, 7), -+ MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents, 0x00A0, 8, 3, 15), -+ MUX_GATE(CLK_TOP_EMMC_HCLK_SEL, "emmc_hclk_sel", emmc_hclk_parents, 0x00A0, 24, 2, 31), -+ -+ MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents, 0x00B0, 0, 3, 7), -+ MUX_GATE(CLK_TOP_DI_SEL, "di_sel", di_parents, 0x00B0, 8, 2, 15), -+ MUX_GATE(CLK_TOP_NR_SEL, "nr_sel", nr_osd_parents, 0x00B0, 16, 3, 23), -+ MUX_GATE(CLK_TOP_OSD_SEL, "osd_sel", nr_osd_parents, 0x00B0, 24, 3, 31), -+ -+ MUX_GATE(CLK_TOP_HDMIRX_BIST_SEL, "hdmirx_bist_sel", hdmirx_bist_parents, 0x00C0, 0, 3, 7), -+ MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents, 0x00C0, 8, 2, 15), -+ MUX_GATE(CLK_TOP_ASM_I_SEL, "asm_i_sel", asm_parents, 0x00C0, 16, 2, 23), -+ MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_parents, 0x00C0, 24, 3, 31), -+ -+ MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_parents, 0x00D0, 0, 2, 7), -+ MUX_GATE(CLK_TOP_MS_CARD_SEL, "ms_card_sel", ms_card_parents, 0x00D0, 16, 2, 23), -+ MUX_GATE(CLK_TOP_ETHIF_SEL, "ethif_sel", ethif_parents, 0x00D0, 24, 3, 31), -+ -+ MUX_GATE(CLK_TOP_HDMIRX26_24_SEL, "hdmirx26_24_sel", hdmirx_parents, 0x00E0, 0, 1, 7), -+ MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, 0x00E0, 8, 3, 15), -+ MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel", cmsys_parents, 0x00E0, 16, 4, 23), -+ -+ MUX_GATE(CLK_TOP_SPI1_SEL, "spi2_sel", spi_parents, 0x00E0, 24, 3, 31), -+ MUX_GATE(CLK_TOP_SPI2_SEL, "spi1_sel", spi_parents, 0x00F0, 0, 3, 7), -+ MUX_GATE(CLK_TOP_8BDAC_SEL, "8bdac_sel", clk_8bdac_parents, 0x00F0, 8, 2, 15), -+ MUX_GATE(CLK_TOP_AUD2DVD_SEL, "aud2dvd_sel", aud2dvd_parents, 0x00F0, 16, 1, 23), -+ -+ MUX(CLK_TOP_PADMCLK_SEL, "padmclk_sel", padmclk_parents, 0x0100, 0, 3), -+ -+ MUX(CLK_TOP_AUD_MUX1_SEL, "aud_mux1_sel", aud_mux_parents, 0x012c, 0, 3), -+ MUX(CLK_TOP_AUD_MUX2_SEL, "aud_mux2_sel", aud_mux_parents, 0x012c, 3, 3), -+ MUX(CLK_TOP_AUDPLL_MUX_SEL, "audpll_sel", aud_mux_parents, 0x012c, 6, 3), -+ MUX_GATE(CLK_TOP_AUD_K1_SRC_SEL, "aud_k1_src_sel", aud_src_parents, 0x012c, 15, 1, 23), -+ MUX_GATE(CLK_TOP_AUD_K2_SRC_SEL, "aud_k2_src_sel", aud_src_parents, 0x012c, 16, 1, 24), -+ MUX_GATE(CLK_TOP_AUD_K3_SRC_SEL, "aud_k3_src_sel", aud_src_parents, 0x012c, 17, 1, 25), -+ MUX_GATE(CLK_TOP_AUD_K4_SRC_SEL, "aud_k4_src_sel", aud_src_parents, 0x012c, 18, 1, 26), -+ MUX_GATE(CLK_TOP_AUD_K5_SRC_SEL, "aud_k5_src_sel", aud_src_parents, 0x012c, 19, 1, 27), -+ MUX_GATE(CLK_TOP_AUD_K6_SRC_SEL, "aud_k6_src_sel", aud_src_parents, 0x012c, 20, 1, 28), -+}; -+ -+static const struct mtk_clk_divider top_adj_divs[] __initconst = { -+ DIV_ADJ(CLK_TOP_AUD_EXTCK1_DIV, "audio_ext1_ck", "aud_ext_ck1", 0x0120, 0, 8), -+ DIV_ADJ(CLK_TOP_AUD_EXTCK2_DIV, "audio_ext2_ck", "aud_ext_ck2", 0x0120, 8, 8), -+ DIV_ADJ(CLK_TOP_AUD_MUX1_DIV, "aud_mux1_div", "aud_mux1_sel", 0x0120, 16, 8), -+ DIV_ADJ(CLK_TOP_AUD_MUX2_DIV, "aud_mux2_div", "aud_mux2_sel", 0x0120, 24, 8), -+ DIV_ADJ(CLK_TOP_AUD_K1_SRC_DIV, "aud_k1_src_div", "aud_k1_src_sel", 0x0124, 0, 8), -+ DIV_ADJ(CLK_TOP_AUD_K2_SRC_DIV, "aud_k2_src_div", "aud_k2_src_sel", 0x0124, 8, 8), -+ DIV_ADJ(CLK_TOP_AUD_K3_SRC_DIV, "aud_k3_src_div", "aud_k3_src_sel", 0x0124, 16, 8), -+ DIV_ADJ(CLK_TOP_AUD_K4_SRC_DIV, "aud_k4_src_div", "aud_k4_src_sel", 0x0124, 24, 8), -+ DIV_ADJ(CLK_TOP_AUD_K5_SRC_DIV, "aud_k5_src_div", "aud_k5_src_sel", 0x0128, 0, 8), -+ DIV_ADJ(CLK_TOP_AUD_K6_SRC_DIV, "aud_k6_src_div", "aud_k6_src_sel", 0x0128, 8, 8), -+}; -+ -+static const struct mtk_gate_regs top_aud_cg_regs __initconst = { -+ .sta_ofs = 0x012C, -+}; -+ -+#define GATE_TOP_AUD(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &top_aud_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_no_setclr, \ -+ } -+ -+static const struct mtk_gate top_clks[] __initconst = { -+ GATE_TOP_AUD(CLK_TOP_AUD_48K_TIMING, "a1sys_hp_ck", "aud_mux1_div", 21), -+ GATE_TOP_AUD(CLK_TOP_AUD_44K_TIMING, "a2sys_hp_ck", "aud_mux2_div", 22), -+ GATE_TOP_AUD(CLK_TOP_AUD_I2S1_MCLK, "aud_i2s1_mclk", "aud_k1_src_div", 23), -+ GATE_TOP_AUD(CLK_TOP_AUD_I2S2_MCLK, "aud_i2s2_mclk", "aud_k2_src_div", 24), -+ GATE_TOP_AUD(CLK_TOP_AUD_I2S3_MCLK, "aud_i2s3_mclk", "aud_k3_src_div", 25), -+ GATE_TOP_AUD(CLK_TOP_AUD_I2S4_MCLK, "aud_i2s4_mclk", "aud_k4_src_div", 26), -+ GATE_TOP_AUD(CLK_TOP_AUD_I2S5_MCLK, "aud_i2s5_mclk", "aud_k5_src_div", 27), -+ GATE_TOP_AUD(CLK_TOP_AUD_I2S6_MCLK, "aud_i2s6_mclk", "aud_k6_src_div", 28), -+}; -+ -+static void __init mtk_topckgen_init(struct device_node *node) -+{ -+ struct clk_onecell_data *clk_data; -+ void __iomem *base; -+ int r; -+ -+ base = of_iomap(node, 0); -+ if (!base) { -+ pr_err("%s(): ioremap failed\n", __func__); -+ return; -+ } -+ -+ clk_data = mtk_alloc_clk_data(CLK_TOP_NR); -+ -+ mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), -+ clk_data); -+ -+ mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs), -+ clk_data); -+ -+ mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), -+ base, &lock, clk_data); -+ -+ mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), -+ base, &lock, clk_data); -+ -+ mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), -+ clk_data); -+ -+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); -+ if (r) -+ pr_err("%s(): could not register clock provider: %d\n", -+ __func__, r); -+} -+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt2701-topckgen", mtk_topckgen_init); -+ -+static const struct mtk_gate_regs infra_cg_regs __initconst = { -+ .set_ofs = 0x0040, -+ .clr_ofs = 0x0044, -+ .sta_ofs = 0x0048, -+}; -+ -+#define GATE_ICG(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &infra_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr, \ -+ } -+ -+static const struct mtk_gate infra_clks[] __initconst = { -+ GATE_ICG(CLK_INFRA_DBG, "dbgclk", "axi_sel", 0), -+ GATE_ICG(CLK_INFRA_SMI, "smi_ck", "mm_sel", 1), -+ GATE_ICG(CLK_INFRA_QAXI_CM4, "cm4_ck", "axi_sel", 2), -+ GATE_ICG(CLK_INFRA_AUD_SPLIN_B, "audio_splin_bck", "hadds2_294m_ck", 4), -+ GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "clk_null", 5), -+ GATE_ICG(CLK_INFRA_EFUSE, "efuse_ck", "clk26m", 6), -+ GATE_ICG(CLK_INFRA_L2C_SRAM, "l2c_sram_ck", "mm_sel", 7), -+ GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8), -+ GATE_ICG(CLK_INFRA_CONNMCU, "connsys_bus", "wbg_dig_ck_416m", 12), -+ GATE_ICG(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 13), -+ GATE_ICG(CLK_INFRA_RAMBUFIF, "rambufif_ck", "mem_sel", 14), -+ GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "mem_sel", 15), -+ GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16), -+ GATE_ICG(CLK_INFRA_CEC, "cec_ck", "rtc_sel", 18), -+ GATE_ICG(CLK_INFRA_IRRX, "irrx_ck", "axi_sel", 19), -+ GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22), -+ GATE_ICG(CLK_INFRA_PMICWRAP, "pmicwrap_ck", "axi_sel", 23), -+ GATE_ICG(CLK_INFRA_DDCCI, "ddcci_ck", "axi_sel", 24), -+}; -+ -+static const struct mtk_fixed_factor infra_fixed_divs[] __initconst = { -+ FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2), -+}; -+ -+static void __init mtk_infrasys_init(struct device_node *node) -+{ -+ struct clk_onecell_data *clk_data; -+ int r; -+ -+ clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); -+ -+ mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), -+ clk_data); -+ mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), -+ clk_data); -+ -+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); -+ if (r) -+ pr_err("%s(): could not register clock provider: %d\n", -+ __func__, r); -+} -+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt2701-infracfg", mtk_infrasys_init); -+ -+static const struct mtk_gate_regs peri0_cg_regs __initconst = { -+ .set_ofs = 0x0008, -+ .clr_ofs = 0x0010, -+ .sta_ofs = 0x0018, -+}; -+ -+static const struct mtk_gate_regs peri1_cg_regs __initconst = { -+ .set_ofs = 0x000c, -+ .clr_ofs = 0x0014, -+ .sta_ofs = 0x001c, -+}; -+ -+#define GATE_PERI0(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &peri0_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr, \ -+ } -+ -+#define GATE_PERI1(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &peri1_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr, \ -+ } -+ -+static const struct mtk_gate peri_clks[] __initconst = { -+ GATE_PERI1(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 31), -+ GATE_PERI1(CLK_PERI_ETH, "eth_ck", "clk26m", 30), -+ GATE_PERI1(CLK_PERI_SPI0, "spi0_ck", "spi0_sel", 29), -+ GATE_PERI1(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 28), -+ GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "clk26m", 27), -+ GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 26), -+ GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 25), -+ GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 24), -+ GATE_PERI0(CLK_PERI_BTIF, "bitif_ck", "axi_sel", 23), -+ GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 22), -+ GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 21), -+ GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 20), -+ GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 19), -+ GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 18), -+ GATE_PERI0(CLK_PERI_MSDC50_3, "msdc50_3_ck", "emmc_hclk_sel", 17), -+ GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_3_sel", 16), -+ GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_2_sel", 15), -+ GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_1_sel", 14), -+ GATE_PERI0(CLK_PERI_MSDC30_0, "msdc30_0_ck", "msdc30_0_sel", 13), -+ GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12), -+ GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11), -+ GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10), -+ GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9), -+ GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8), -+ GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7), -+ GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6), -+ GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5), -+ GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4), -+ GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3), -+ GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2), -+ GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1), -+ GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "nfi2x_sel", 0), -+ -+ GATE_PERI1(CLK_PERI_FCI, "fci_ck", "ms_card", 11), -+ GATE_PERI1(CLK_PERI_SPI2, "spi2_ck", "spi2_sel", 10), -+ GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi1_sel", 9), -+ GATE_PERI1(CLK_PERI_HOST89_DVD, "host89_dvd_ck", "aud2dvd_sel", 8), -+ GATE_PERI1(CLK_PERI_HOST89_SPI, "host89_spi_ck", "spi0_sel", 7), -+ GATE_PERI1(CLK_PERI_HOST89_INT, "host89_int_ck", "axi_sel", 6), -+ GATE_PERI1(CLK_PERI_FLASH, "flash_ck", "nfi2x_sel", 5), -+ GATE_PERI1(CLK_PERI_NFI_PAD, "nfi_pad_ck", "nfi_sel", 4), -+ GATE_PERI1(CLK_PERI_NFI_ECC, "nfi_ecc_ck", "nfi_sel", 3), -+ GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "axi_sel", 2), -+ GATE_PERI1(CLK_PERI_USB_SLV, "usbslv_ck", "axi_sel", 1), -+ GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 0), -+}; -+ -+static const char * const uart_ck_sel_parents[] __initconst = { -+ "clk26m", -+ "uart_sel", -+}; -+ -+static const struct mtk_composite peri_muxs[] __initconst = { -+ MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1), -+ MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1), -+ MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1), -+ MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1), -+}; -+ -+static void __init mtk_pericfg_init(struct device_node *node) -+{ -+ struct clk_onecell_data *clk_data; -+ void __iomem *base; -+ int r; -+ -+ base = of_iomap(node, 0); -+ if (!base) { -+ pr_err("%s(): ioremap failed\n", __func__); -+ return; -+ } -+ -+ clk_data = mtk_alloc_clk_data(CLK_PERI_NR); -+ -+ mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), -+ clk_data); -+ -+ mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base, -+ &lock, clk_data); -+ -+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); -+ if (r) -+ pr_err("%s(): could not register clock provider: %d\n", -+ __func__, r); -+} -+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt2701-pericfg", mtk_pericfg_init); -+ -+static const struct mtk_gate_regs disp0_cg_regs __initconst = { -+ .set_ofs = 0x0104, -+ .clr_ofs = 0x0108, -+ .sta_ofs = 0x0100, -+}; -+ -+static const struct mtk_gate_regs disp1_cg_regs __initconst = { -+ .set_ofs = 0x0114, -+ .clr_ofs = 0x0118, -+ .sta_ofs = 0x0110, -+}; -+ -+#define GATE_DISP0(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &disp0_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr, \ -+ } -+ -+#define GATE_DISP1(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &disp1_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr, \ -+ } -+ -+static const struct mtk_gate mm_clks[] __initconst = { -+ GATE_DISP0(CLK_MM_SMI_COMMON, "mm_smi_comm", "mm_sel", 0), -+ GATE_DISP0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1), -+ GATE_DISP0(CLK_MM_CMDQ, "mm_cmdq", "mm_sel", 2), -+ GATE_DISP0(CLK_MM_MUTEX, "mm_mutex", "mm_sel", 3), -+ GATE_DISP0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 4), -+ GATE_DISP0(CLK_MM_DISP_BLS, "mm_disp_bls", "mm_sel", 5), -+ GATE_DISP0(CLK_MM_DISP_WDMA, "mm_disp_wdma", "mm_sel", 6), -+ GATE_DISP0(CLK_MM_DISP_RDMA, "mm_disp_rdma", "mm_sel", 7), -+ GATE_DISP0(CLK_MM_DISP_OVL, "mm_disp_ovl", "mm_sel", 8), -+ GATE_DISP0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9), -+ GATE_DISP0(CLK_MM_MDP_WROT, "mm_mdp_wrot", "mm_sel", 10), -+ GATE_DISP0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11), -+ GATE_DISP0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 12), -+ GATE_DISP0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 13), -+ GATE_DISP0(CLK_MM_MDP_RDMA, "mm_mdp_rdma", "mm_sel", 14), -+ GATE_DISP0(CLK_MM_MDP_BLS_26M, "mm_mdp_bls_26m", "clk26m", 15), -+ GATE_DISP0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 16), -+ GATE_DISP0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 17), -+ GATE_DISP0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 18), -+ GATE_DISP0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19), -+ GATE_DISP0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 20), -+ GATE_DISP1(CLK_MM_DSI_ENGINE, "mm_dsi_eng", "mm_sel", 0), -+ GATE_DISP1(CLK_MM_DSI_DIG, "mm_dsi_dig", "dsio_lntc_dsiclk", 1), -+ GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2), -+ GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3), -+ GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4), -+ GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5), -+ GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6), -+ GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7), -+ GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8), -+ GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9), -+ GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10), -+ GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11), -+ GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14), -+}; -+ -+static void __init mtk_mmsys_init(struct device_node *node) -+{ -+ struct clk_onecell_data *clk_data; -+ int r; -+ -+ clk_data = mtk_alloc_clk_data(CLK_MM_NR); -+ -+ mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), -+ clk_data); -+ -+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); -+ if (r) -+ pr_err("%s(): could not register clock provider: %d\n", -+ __func__, r); -+} -+CLK_OF_DECLARE(mtk_mmsys, "mediatek,mt2701-mmsys", mtk_mmsys_init); -+ -+static const struct mtk_gate_regs img_cg_regs __initconst = { -+ .set_ofs = 0x0004, -+ .clr_ofs = 0x0008, -+ .sta_ofs = 0x0000, -+}; -+ -+#define GATE_IMG(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &img_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr, \ -+ } -+ -+static const struct mtk_gate img_clks[] __initconst = { -+ GATE_IMG(CLK_IMG_SMI_COMM, "img_smi_comm", "mm_sel", 0), -+ GATE_IMG(CLK_IMG_RESZ, "img_resz", "mm_sel", 1), -+ GATE_IMG(CLK_IMG_JPGDEC, "img_jpgdec", "mm_sel", 5), -+ GATE_IMG(CLK_IMG_VENC_LT, "img_venc_lt", "mm_sel", 8), -+ GATE_IMG(CLK_IMG_VENC, "img_venc", "mm_sel", 9), -+}; -+ -+static void __init mtk_imgsys_init(struct device_node *node) -+{ -+ struct clk_onecell_data *clk_data; -+ int r; -+ -+ clk_data = mtk_alloc_clk_data(CLK_IMG_NR); -+ -+ mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), -+ clk_data); -+ -+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); -+ if (r) -+ pr_err("%s(): could not register clock provider: %d\n", -+ __func__, r); -+} -+CLK_OF_DECLARE(mtk_imgsys, "mediatek,mt2701-imgsys", mtk_imgsys_init); -+ -+static const struct mtk_gate_regs vdec0_cg_regs __initconst = { -+ .set_ofs = 0x0000, -+ .clr_ofs = 0x0004, -+ .sta_ofs = 0x0000, -+}; -+ -+static const struct mtk_gate_regs vdec1_cg_regs __initconst = { -+ .set_ofs = 0x0008, -+ .clr_ofs = 0x000c, -+ .sta_ofs = 0x0008, -+}; -+ -+#define GATE_VDEC0(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &vdec0_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr_inv, \ -+ } -+ -+#define GATE_VDEC1(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &vdec1_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr_inv, \ -+ } -+ -+static const struct mtk_gate vdec_clks[] __initconst = { -+ GATE_VDEC0(CLK_VDEC_CKGEN, "vdec_cken", "vdec_sel", 0), -+ GATE_VDEC1(CLK_VDEC_LARB, "vdec_larb_cken", "mm_sel", 0), -+}; -+ -+static void __init mtk_vdecsys_init(struct device_node *node) -+{ -+ struct clk_onecell_data *clk_data; -+ int r; -+ -+ clk_data = mtk_alloc_clk_data(CLK_VDEC_NR); -+ -+ mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), -+ clk_data); -+ -+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); -+ if (r) -+ pr_err("%s(): could not register clock provider: %d\n", -+ __func__, r); -+} -+CLK_OF_DECLARE(mtk_vdecsys, "mediatek,mt2701-vdecsys", mtk_vdecsys_init); -+ -+static const struct mtk_gate_regs hif_cg_regs __initconst = { -+ .sta_ofs = 0x0008, -+}; -+ -+#define GATE_HIF(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &hif_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ -+ } -+ -+static const struct mtk_gate hif_clks[] __initconst = { -+ GATE_HIF(CLK_HIFSYS_USB0PHY, "usb0_phy_clk", "ethpll_500m_ck", 21), -+ GATE_HIF(CLK_HIFSYS_USB1PHY, "usb1_phy_clk", "ethpll_500m_ck", 22), -+ GATE_HIF(CLK_HIFSYS_PCIE0, "pcie0_clk", "ethpll_500m_ck", 24), -+ GATE_HIF(CLK_HIFSYS_PCIE1, "pcie1_clk", "ethpll_500m_ck", 25), -+ GATE_HIF(CLK_HIFSYS_PCIE2, "pcie2_clk", "ethpll_500m_ck", 26), -+}; -+ -+static void __init mtk_hifsys_init(struct device_node *node) -+{ -+ struct clk_onecell_data *clk_data; -+ int r; -+ -+ clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR); -+ -+ mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks), -+ clk_data); -+ -+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); -+ if (r) -+ pr_err("%s(): could not register clock provider: %d\n", -+ __func__, r); -+} -+CLK_OF_DECLARE(mtk_hifsys, "mediatek,mt2701-hifsys", mtk_hifsys_init); -+ -+static const struct mtk_gate_regs eth_cg_regs __initconst = { -+ .sta_ofs = 0x0030, -+}; -+ -+#define GATE_eth(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = ð_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_no_setclr_inv, \ -+ } -+ -+static const struct mtk_gate eth_clks[] __initconst = { -+ GATE_HIF(CLK_ETHSYS_HSDMA, "hsdma_clk", "ethif_sel", 5), -+ GATE_HIF(CLK_ETHSYS_ESW, "esw_clk", "ethpll_500m_ck", 6), -+ GATE_HIF(CLK_ETHSYS_GP2, "gp2_clk", "trgpll", 7), -+ GATE_HIF(CLK_ETHSYS_GP1, "gp1_clk", "ethpll_500m_ck", 8), -+ GATE_HIF(CLK_ETHSYS_PCM, "pcm_clk", "ethif_sel", 11), -+ GATE_HIF(CLK_ETHSYS_GDMA, "gdma_clk", "ethif_sel", 14), -+ GATE_HIF(CLK_ETHSYS_I2S, "i2s_clk", "ethif_sel", 17), -+ GATE_HIF(CLK_ETHSYS_CRYPTO, "crypto_clk", "ethif_sel", 29), -+}; -+ -+static void __init mtk_ethsys_init(struct device_node *node) -+{ -+ struct clk_onecell_data *clk_data; -+ int r; -+ -+ clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR); -+ -+ mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), -+ clk_data); -+ -+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); -+ if (r) -+ pr_err("%s(): could not register clock provider: %d\n", -+ __func__, r); -+} -+CLK_OF_DECLARE(mtk_ethsys, "mediatek,mt2701-ethsys", mtk_ethsys_init); -+ -+static const struct mtk_gate_regs bdp0_cg_regs __initconst = { -+ .set_ofs = 0x0104, -+ .clr_ofs = 0x0108, -+ .sta_ofs = 0x0100, -+}; -+ -+static const struct mtk_gate_regs bdp1_cg_regs __initconst = { -+ .set_ofs = 0x0114, -+ .clr_ofs = 0x0118, -+ .sta_ofs = 0x0110, -+}; -+ -+#define GATE_BDP0(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &bdp0_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr_inv, \ -+ } -+ -+#define GATE_BDP1(_id, _name, _parent, _shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .regs = &bdp1_cg_regs, \ -+ .shift = _shift, \ -+ .ops = &mtk_clk_gate_ops_setclr_inv, \ -+ } -+ -+static const struct mtk_gate bdp_clks[] __initconst = { -+ GATE_BDP0(CLK_BDP_BRG_BA, "brg_baclk", "mm_sel", 0), -+ GATE_BDP0(CLK_BDP_BRG_DRAM, "brg_dram", "mm_sel", 1), -+ GATE_BDP0(CLK_BDP_LARB_DRAM, "larb_dram", "mm_sel", 2), -+ GATE_BDP0(CLK_BDP_WR_VDI_PXL, "wr_vdi_pxl", "hdmi_0_deep340m", 3), -+ GATE_BDP0(CLK_BDP_WR_VDI_DRAM, "wr_vdi_dram", "mm_sel", 4), -+ GATE_BDP0(CLK_BDP_WR_B, "wr_bclk", "mm_sel", 5), -+ GATE_BDP0(CLK_BDP_DGI_IN, "dgi_in", "dpi1_sel", 6), -+ GATE_BDP0(CLK_BDP_DGI_OUT, "dgi_out", "dpi_sel", 7), -+ GATE_BDP0(CLK_BDP_FMT_MAST_27, "fmt_mast_27", "dpi1_sel", 8), -+ GATE_BDP0(CLK_BDP_FMT_B, "fmt_bclk", "mm_sel", 9), -+ GATE_BDP0(CLK_BDP_OSD_B, "osd_bclk", "mm_sel", 10), -+ GATE_BDP0(CLK_BDP_OSD_DRAM, "osd_dram", "mm_sel", 11), -+ GATE_BDP0(CLK_BDP_OSD_AGENT, "osd_agent", "osd_sel", 12), -+ GATE_BDP0(CLK_BDP_OSD_PXL, "osd_pxl", "dpi1_sel", 13), -+ GATE_BDP0(CLK_BDP_RLE_B, "rle_bclk", "mm_sel", 14), -+ GATE_BDP0(CLK_BDP_RLE_AGENT, "rle_agent", "mm_sel", 15), -+ GATE_BDP0(CLK_BDP_RLE_DRAM, "rle_dram", "mm_sel", 16), -+ GATE_BDP0(CLK_BDP_F27M, "f27m", "di_sel", 17), -+ GATE_BDP0(CLK_BDP_F27M_VDOUT, "f27m_vdout", "di_sel", 18), -+ GATE_BDP0(CLK_BDP_F27_74_74, "f27_74_74", "di_sel", 19), -+ GATE_BDP0(CLK_BDP_F2FS, "f2fs", "di_sel", 20), -+ GATE_BDP0(CLK_BDP_F2FS74_148, "f2fs74_148", "di_sel", 21), -+ GATE_BDP0(CLK_BDP_FB, "fbclk", "mm_sel", 22), -+ GATE_BDP0(CLK_BDP_VDO_DRAM, "vdo_dram", "mm_sel", 23), -+ GATE_BDP0(CLK_BDP_VDO_2FS, "vdo_2fs", "di_sel", 24), -+ GATE_BDP0(CLK_BDP_VDO_B, "vdo_bclk", "mm_sel", 25), -+ GATE_BDP0(CLK_BDP_WR_DI_PXL, "wr_di_pxl", "di_sel", 26), -+ GATE_BDP0(CLK_BDP_WR_DI_DRAM, "wr_di_dram", "mm_sel", 27), -+ GATE_BDP0(CLK_BDP_WR_DI_B, "wr_di_bclk", "mm_sel", 28), -+ GATE_BDP0(CLK_BDP_NR_PXL, "nr_pxl", "nr_sel", 29), -+ GATE_BDP0(CLK_BDP_NR_DRAM, "nr_dram", "mm_sel", 30), -+ GATE_BDP0(CLK_BDP_NR_B, "nr_bclk", "mm_sel", 31), -+ GATE_BDP1(CLK_BDP_RX_F, "rx_fclk", "hadds2_fbclk", 0), -+ GATE_BDP1(CLK_BDP_RX_X, "rx_xclk", "clk26m", 1), -+ GATE_BDP1(CLK_BDP_RXPDT, "rxpdtclk", "hdmi_0_pix340m", 2), -+ GATE_BDP1(CLK_BDP_RX_CSCL_N, "rx_cscl_n", "clk26m", 3), -+ GATE_BDP1(CLK_BDP_RX_CSCL, "rx_cscl", "clk26m", 4), -+ GATE_BDP1(CLK_BDP_RX_DDCSCL_N, "rx_ddcscl_n", "hdmi_scl_rx", 5), -+ GATE_BDP1(CLK_BDP_RX_DDCSCL, "rx_ddcscl", "hdmi_scl_rx", 6), -+ GATE_BDP1(CLK_BDP_RX_VCO, "rx_vcoclk", "hadds2pll_294m", 7), -+ GATE_BDP1(CLK_BDP_RX_DP, "rx_dpclk", "hdmi_0_pll340m", 8), -+ GATE_BDP1(CLK_BDP_RX_P, "rx_pclk", "hdmi_0_pll340m", 9), -+ GATE_BDP1(CLK_BDP_RX_M, "rx_mclk", "hadds2pll_294m", 10), -+ GATE_BDP1(CLK_BDP_RX_PLL, "rx_pllclk", "hdmi_0_pix340m", 11), -+ GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12), -+ GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13), -+ GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14), -+ GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15), -+ GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_mon", 16), -+}; -+ -+static void __init mtk_bdpsys_init(struct device_node *node) -+{ -+ struct clk_onecell_data *clk_data; -+ int r; -+ -+ clk_data = mtk_alloc_clk_data(CLK_BDP_NR); -+ -+ mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks), -+ clk_data); -+ -+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); -+ if (r) -+ pr_err("%s(): could not register clock provider: %d\n", -+ __func__, r); -+} -+CLK_OF_DECLARE(mtk_bdpsys, "mediatek,mt2701-bdpsys", mtk_bdpsys_init); -+ -+#define MT8590_PLL_FMAX (2000 * MHZ) -+#define CON0_MT8590_RST_BAR BIT(27) -+ -+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \ -+ _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .reg = _reg, \ -+ .pwr_reg = _pwr_reg, \ -+ .en_mask = _en_mask, \ -+ .flags = _flags, \ -+ .rst_bar_mask = CON0_MT8590_RST_BAR, \ -+ .fmax = MT8590_PLL_FMAX, \ -+ .pcwbits = _pcwbits, \ -+ .pd_reg = _pd_reg, \ -+ .pd_shift = _pd_shift, \ -+ .tuner_reg = _tuner_reg, \ -+ .pcw_reg = _pcw_reg, \ -+ .pcw_shift = _pcw_shift, \ -+ } -+ -+static const struct mtk_pll_data apmixed_plls[] = { -+ PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x80000001, 0, -+ 21, 0x204, 24, 0x0, 0x204, 0), -+ PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0xf0000001, -+ HAVE_RST_BAR, 21, 0x210, 4, 0x0, 0x214, 0), -+ PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xf3000001, -+ HAVE_RST_BAR, 7, 0x220, 4, 0x0, 0x224, 14), -+ PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0x00000001, 0, -+ 21, 0x230, 4, 0x0, 0x234, 0), -+ PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0, -+ 21, 0x240, 4, 0x0, 0x244, 0), -+ PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x250, 0x25c, 0x00000001, 0, -+ 21, 0x250, 4, 0x0, 0x254, 0), -+ PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x270, 0x27c, 0x00000001, 0, -+ 31, 0x270, 4, 0x0, 0x274, 0), -+ PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x280, 0x28c, 0x00000001, 0, -+ 31, 0x280, 4, 0x0, 0x284, 0), -+ PLL(CLK_APMIXED_ETHPLL, "ethpll", 0x290, 0x29c, 0x00000001, 0, -+ 31, 0x290, 4, 0x0, 0x294, 0), -+ PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x2a0, 0x2ac, 0x00000001, 0, -+ 31, 0x2a0, 4, 0x0, 0x2a4, 0), -+ PLL(CLK_APMIXED_HADDS2PLL, "hadds2pll", 0x2b0, 0x2bc, 0x00000001, 0, -+ 31, 0x2b0, 4, 0x0, 0x2b4, 0), -+ PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x2c0, 0x2cc, 0x00000001, 0, -+ 31, 0x2c0, 4, 0x0, 0x2c4, 0), -+ PLL(CLK_APMIXED_TVD2PLL, "tvd2pll", 0x2d0, 0x2dc, 0x00000001, 0, -+ 21, 0x2d0, 4, 0x0, 0x2d4, 0), -+}; -+ -+static void __init mtk_apmixedsys_init(struct device_node *node) -+{ -+ struct clk_onecell_data *clk_data; -+ int r; -+ -+ clk_data = mtk_alloc_clk_data(ARRAY_SIZE(apmixed_plls)); -+ if (!clk_data) -+ return; -+ -+ mtk_clk_register_plls(node, apmixed_plls, ARRAY_SIZE(apmixed_plls), -+ clk_data); -+ -+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); -+ if (r) -+ pr_err("%s(): could not register clock provider: %d\n", -+ __func__, r); -+} -+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt2701-apmixedsys", -+ mtk_apmixedsys_init); ---- a/drivers/clk/mediatek/clk-mtk.c -+++ b/drivers/clk/mediatek/clk-mtk.c -@@ -244,3 +244,28 @@ void mtk_clk_register_composites(const s - clk_data->clks[mc->id] = clk; - } - } -+ -+void __init mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, -+ int num, void __iomem *base, spinlock_t *lock, -+ struct clk_onecell_data *clk_data) -+{ -+ struct clk *clk; -+ int i; -+ -+ for (i = 0; i < num; i++) { -+ const struct mtk_clk_divider *mcd = &mcds[i]; -+ -+ clk = clk_register_divider(NULL, mcd->name, mcd->parent_name, -+ mcd->flags, base + mcd->div_reg, mcd->div_shift, -+ mcd->div_width, mcd->clk_divider_flags, lock); -+ -+ if (IS_ERR(clk)) { -+ pr_err("Failed to register clk %s: %ld\n", -+ mcd->name, PTR_ERR(clk)); -+ continue; -+ } -+ -+ if (clk_data) -+ clk_data->clks[mcd->id] = clk; -+ } -+} ---- a/drivers/clk/mediatek/clk-mtk.h -+++ b/drivers/clk/mediatek/clk-mtk.h -@@ -121,7 +121,8 @@ struct mtk_composite { - .flags = CLK_SET_RATE_PARENT, \ - } - --#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) { \ -+#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \ -+ _div_width, _div_shift) { \ - .id = _id, \ - .parent = _parent, \ - .name = _name, \ -@@ -156,8 +157,36 @@ struct mtk_gate { - const struct clk_ops *ops; - }; - --int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks, -- int num, struct clk_onecell_data *clk_data); -+int mtk_clk_register_gates(struct device_node *node, -+ const struct mtk_gate *clks, int num, -+ struct clk_onecell_data *clk_data); -+ -+struct mtk_clk_divider { -+ int id; -+ const char *name; -+ const char *parent_name; -+ unsigned long flags; -+ -+ uint32_t div_reg; -+ unsigned char div_shift; -+ unsigned char div_width; -+ unsigned char clk_divider_flags; -+ const struct clk_div_table *clk_div_table; -+}; -+ -+#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) { \ -+ .id = _id, \ -+ .name = _name, \ -+ .parent_name = _parent, \ -+ .flags = CLK_SET_RATE_PARENT, \ -+ .div_reg = _reg, \ -+ .div_shift = _shift, \ -+ .div_width = _width, \ -+} -+ -+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, -+ int num, void __iomem *base, spinlock_t *lock, -+ struct clk_onecell_data *clk_data); - - struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); - diff --git a/target/linux/mediatek/patches-4.9/0006-reset-mediatek-mt2701-reset-driver.patch b/target/linux/mediatek/patches-4.9/0006-reset-mediatek-mt2701-reset-driver.patch deleted file mode 100644 index 12bda9c..0000000 --- a/target/linux/mediatek/patches-4.9/0006-reset-mediatek-mt2701-reset-driver.patch +++ /dev/null @@ -1,36 +0,0 @@ -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 06/57] reset: mediatek: mt2701 reset driver - -In infrasys and perifsys, there are many reset -control bits for kinds of modules. These bits are -used as actual reset controllers to be registered -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 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/clk/mediatek/clk-mt2701.c -+++ b/drivers/clk/mediatek/clk-mt2701.c -@@ -665,6 +665,8 @@ static void __init mtk_infrasys_init(str - if (r) - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); -+ -+ mtk_register_reset_controller(node, 2, 0x30); - } - CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt2701-infracfg", mtk_infrasys_init); - -@@ -782,6 +784,8 @@ static void __init mtk_pericfg_init(stru - if (r) - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); -+ -+ mtk_register_reset_controller(node, 2, 0x0); - } - CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt2701-pericfg", mtk_pericfg_init); - diff --git a/target/linux/mediatek/patches-4.9/0007-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 deleted file mode 100644 index f38b435..0000000 --- a/target/linux/mediatek/patches-4.9/0007-ARM-mediatek-Add-MT2701-config-options-for-mediatek-.patch +++ /dev/null @@ -1,29 +0,0 @@ -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 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. -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 ++++ - 1 file changed, 4 insertions(+) - ---- a/arch/arm/mach-mediatek/Kconfig -+++ b/arch/arm/mach-mediatek/Kconfig -@@ -14,6 +14,10 @@ config MACH_MT2701 - bool "MediaTek MT2701 SoCs support" - default ARCH_MEDIATEK - -+config MACH_MT2701 -+ bool "MediaTek MT2701 SoCs support" -+ default ARCH_MEDIATEK -+ - config MACH_MT6589 - bool "MediaTek MT6589 SoCs support" - default ARCH_MEDIATEK diff --git a/target/linux/mediatek/patches-4.9/0008-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 deleted file mode 100644 index 1d83e9a..0000000 --- a/target/linux/mediatek/patches-4.9/0008-soc-mediatek-Refine-scpsys-to-support-multiple-platf.patch +++ /dev/null @@ -1,487 +0,0 @@ -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 08/57] soc: mediatek: Refine scpsys to support multiple - platform - -Refine scpsys driver common code to support multiple SoC / platform. - -Signed-off-by: James Liao <jamesjj.liao@mediatek.com> -Reviewed-by: Kevin Hilman <khilman@baylibre.com> -Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com> ---- - drivers/soc/mediatek/mtk-scpsys.c | 348 +++++++++++++++++++++++--------------- - 1 file changed, 210 insertions(+), 138 deletions(-) - ---- a/drivers/soc/mediatek/mtk-scpsys.c -+++ b/drivers/soc/mediatek/mtk-scpsys.c -@@ -11,17 +11,15 @@ - * GNU General Public License for more details. - */ - #include <linux/clk.h> --#include <linux/delay.h> -+#include <linux/init.h> - #include <linux/io.h> --#include <linux/kernel.h> - #include <linux/mfd/syscon.h> --#include <linux/init.h> - #include <linux/of_device.h> - #include <linux/platform_device.h> - #include <linux/pm_domain.h> --#include <linux/regmap.h> --#include <linux/soc/mediatek/infracfg.h> - #include <linux/regulator/consumer.h> -+#include <linux/soc/mediatek/infracfg.h> -+ - #include <dt-bindings/power/mt8173-power.h> - - #define SPM_VDE_PWR_CON 0x0210 -@@ -34,6 +32,7 @@ - #define SPM_MFG_2D_PWR_CON 0x02c0 - #define SPM_MFG_ASYNC_PWR_CON 0x02c4 - #define SPM_USB_PWR_CON 0x02cc -+ - #define SPM_PWR_STATUS 0x060c - #define SPM_PWR_STATUS_2ND 0x0610 - -@@ -55,12 +54,21 @@ - #define PWR_STATUS_USB BIT(25) - - enum clk_id { -- MT8173_CLK_NONE, -- MT8173_CLK_MM, -- MT8173_CLK_MFG, -- MT8173_CLK_VENC, -- MT8173_CLK_VENC_LT, -- MT8173_CLK_MAX, -+ CLK_NONE, -+ CLK_MM, -+ CLK_MFG, -+ CLK_VENC, -+ CLK_VENC_LT, -+ CLK_MAX, -+}; -+ -+static const char * const clk_names[] = { -+ NULL, -+ "mm", -+ "mfg", -+ "venc", -+ "venc_lt", -+ NULL, - }; - - #define MAX_CLKS 2 -@@ -76,98 +84,6 @@ struct scp_domain_data { - bool active_wakeup; - }; - --static const struct scp_domain_data scp_domain_data[] = { -- [MT8173_POWER_DOMAIN_VDEC] = { -- .name = "vdec", -- .sta_mask = PWR_STATUS_VDEC, -- .ctl_offs = SPM_VDE_PWR_CON, -- .sram_pdn_bits = GENMASK(11, 8), -- .sram_pdn_ack_bits = GENMASK(12, 12), -- .clk_id = {MT8173_CLK_MM}, -- }, -- [MT8173_POWER_DOMAIN_VENC] = { -- .name = "venc", -- .sta_mask = PWR_STATUS_VENC, -- .ctl_offs = SPM_VEN_PWR_CON, -- .sram_pdn_bits = GENMASK(11, 8), -- .sram_pdn_ack_bits = GENMASK(15, 12), -- .clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC}, -- }, -- [MT8173_POWER_DOMAIN_ISP] = { -- .name = "isp", -- .sta_mask = PWR_STATUS_ISP, -- .ctl_offs = SPM_ISP_PWR_CON, -- .sram_pdn_bits = GENMASK(11, 8), -- .sram_pdn_ack_bits = GENMASK(13, 12), -- .clk_id = {MT8173_CLK_MM}, -- }, -- [MT8173_POWER_DOMAIN_MM] = { -- .name = "mm", -- .sta_mask = PWR_STATUS_DISP, -- .ctl_offs = SPM_DIS_PWR_CON, -- .sram_pdn_bits = GENMASK(11, 8), -- .sram_pdn_ack_bits = GENMASK(12, 12), -- .clk_id = {MT8173_CLK_MM}, -- .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | -- MT8173_TOP_AXI_PROT_EN_MM_M1, -- }, -- [MT8173_POWER_DOMAIN_VENC_LT] = { -- .name = "venc_lt", -- .sta_mask = PWR_STATUS_VENC_LT, -- .ctl_offs = SPM_VEN2_PWR_CON, -- .sram_pdn_bits = GENMASK(11, 8), -- .sram_pdn_ack_bits = GENMASK(15, 12), -- .clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC_LT}, -- }, -- [MT8173_POWER_DOMAIN_AUDIO] = { -- .name = "audio", -- .sta_mask = PWR_STATUS_AUDIO, -- .ctl_offs = SPM_AUDIO_PWR_CON, -- .sram_pdn_bits = GENMASK(11, 8), -- .sram_pdn_ack_bits = GENMASK(15, 12), -- .clk_id = {MT8173_CLK_NONE}, -- }, -- [MT8173_POWER_DOMAIN_USB] = { -- .name = "usb", -- .sta_mask = PWR_STATUS_USB, -- .ctl_offs = SPM_USB_PWR_CON, -- .sram_pdn_bits = GENMASK(11, 8), -- .sram_pdn_ack_bits = GENMASK(15, 12), -- .clk_id = {MT8173_CLK_NONE}, -- .active_wakeup = true, -- }, -- [MT8173_POWER_DOMAIN_MFG_ASYNC] = { -- .name = "mfg_async", -- .sta_mask = PWR_STATUS_MFG_ASYNC, -- .ctl_offs = SPM_MFG_ASYNC_PWR_CON, -- .sram_pdn_bits = GENMASK(11, 8), -- .sram_pdn_ack_bits = 0, -- .clk_id = {MT8173_CLK_MFG}, -- }, -- [MT8173_POWER_DOMAIN_MFG_2D] = { -- .name = "mfg_2d", -- .sta_mask = PWR_STATUS_MFG_2D, -- .ctl_offs = SPM_MFG_2D_PWR_CON, -- .sram_pdn_bits = GENMASK(11, 8), -- .sram_pdn_ack_bits = GENMASK(13, 12), -- .clk_id = {MT8173_CLK_NONE}, -- }, -- [MT8173_POWER_DOMAIN_MFG] = { -- .name = "mfg", -- .sta_mask = PWR_STATUS_MFG, -- .ctl_offs = SPM_MFG_PWR_CON, -- .sram_pdn_bits = GENMASK(13, 8), -- .sram_pdn_ack_bits = GENMASK(21, 16), -- .clk_id = {MT8173_CLK_NONE}, -- .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | -- MT8173_TOP_AXI_PROT_EN_MFG_M0 | -- MT8173_TOP_AXI_PROT_EN_MFG_M1 | -- MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT, -- }, --}; -- --#define NUM_DOMAINS ARRAY_SIZE(scp_domain_data) -- - struct scp; - - struct scp_domain { -@@ -179,7 +95,7 @@ struct scp_domain { - }; - - struct scp { -- struct scp_domain domains[NUM_DOMAINS]; -+ struct scp_domain *domains; - struct genpd_onecell_data pd_data; - struct device *dev; - void __iomem *base; -@@ -408,57 +324,55 @@ static bool scpsys_active_wakeup(struct - return scpd->data->active_wakeup; - } - --static int scpsys_probe(struct platform_device *pdev) -+static void init_clks(struct platform_device *pdev, struct clk **clk) -+{ -+ int i; -+ -+ for (i = CLK_NONE + 1; i < CLK_MAX; i++) -+ clk[i] = devm_clk_get(&pdev->dev, clk_names[i]); -+} -+ -+static struct scp *init_scp(struct platform_device *pdev, -+ const struct scp_domain_data *scp_domain_data, int num) - { - struct genpd_onecell_data *pd_data; - struct resource *res; -- int i, j, ret; -+ int i, j; - struct scp *scp; -- struct clk *clk[MT8173_CLK_MAX]; -+ struct clk *clk[CLK_MAX]; - - scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL); - if (!scp) -- return -ENOMEM; -+ return ERR_PTR(-ENOMEM); - - scp->dev = &pdev->dev; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - scp->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(scp->base)) -- return PTR_ERR(scp->base); -+ return ERR_CAST(scp->base); -+ -+ scp->domains = devm_kzalloc(&pdev->dev, -+ sizeof(*scp->domains) * num, GFP_KERNEL); -+ if (!scp->domains) -+ return ERR_PTR(-ENOMEM); - - pd_data = &scp->pd_data; - - pd_data->domains = devm_kzalloc(&pdev->dev, -- sizeof(*pd_data->domains) * NUM_DOMAINS, GFP_KERNEL); -+ sizeof(*pd_data->domains) * num, GFP_KERNEL); - if (!pd_data->domains) -- return -ENOMEM; -- -- clk[MT8173_CLK_MM] = devm_clk_get(&pdev->dev, "mm"); -- if (IS_ERR(clk[MT8173_CLK_MM])) -- return PTR_ERR(clk[MT8173_CLK_MM]); -- -- clk[MT8173_CLK_MFG] = devm_clk_get(&pdev->dev, "mfg"); -- if (IS_ERR(clk[MT8173_CLK_MFG])) -- return PTR_ERR(clk[MT8173_CLK_MFG]); -- -- clk[MT8173_CLK_VENC] = devm_clk_get(&pdev->dev, "venc"); -- if (IS_ERR(clk[MT8173_CLK_VENC])) -- return PTR_ERR(clk[MT8173_CLK_VENC]); -- -- clk[MT8173_CLK_VENC_LT] = devm_clk_get(&pdev->dev, "venc_lt"); -- if (IS_ERR(clk[MT8173_CLK_VENC_LT])) -- return PTR_ERR(clk[MT8173_CLK_VENC_LT]); -+ return ERR_PTR(-ENOMEM); - - scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, - "infracfg"); - if (IS_ERR(scp->infracfg)) { - dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n", - PTR_ERR(scp->infracfg)); -- return PTR_ERR(scp->infracfg); -+ return ERR_CAST(scp->infracfg); - } - -- for (i = 0; i < NUM_DOMAINS; i++) { -+ for (i = 0; i < num; i++) { - struct scp_domain *scpd = &scp->domains[i]; - const struct scp_domain_data *data = &scp_domain_data[i]; - -@@ -467,13 +381,15 @@ static int scpsys_probe(struct platform_ - if (PTR_ERR(scpd->supply) == -ENODEV) - scpd->supply = NULL; - else -- return PTR_ERR(scpd->supply); -+ return ERR_CAST(scpd->supply); - } - } - -- pd_data->num_domains = NUM_DOMAINS; -+ pd_data->num_domains = num; -+ -+ init_clks(pdev, clk); - -- for (i = 0; i < NUM_DOMAINS; i++) { -+ for (i = 0; i < num; i++) { - struct scp_domain *scpd = &scp->domains[i]; - struct generic_pm_domain *genpd = &scpd->genpd; - const struct scp_domain_data *data = &scp_domain_data[i]; -@@ -482,13 +398,37 @@ static int scpsys_probe(struct platform_ - scpd->scp = scp; - - scpd->data = data; -- for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) -- scpd->clk[j] = clk[data->clk_id[j]]; -+ -+ for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) { -+ struct clk *c = clk[data->clk_id[j]]; -+ -+ if (IS_ERR(c)) { -+ dev_err(&pdev->dev, "%s: clk unavailable\n", -+ data->name); -+ return ERR_CAST(c); -+ } -+ -+ scpd->clk[j] = c; -+ } - - genpd->name = data->name; - genpd->power_off = scpsys_power_off; - genpd->power_on = scpsys_power_on; - genpd->dev_ops.active_wakeup = scpsys_active_wakeup; -+ } -+ -+ return scp; -+} -+ -+static void mtk_register_power_domains(struct platform_device *pdev, -+ struct scp *scp, int num) -+{ -+ struct genpd_onecell_data *pd_data; -+ int i, ret; -+ -+ for (i = 0; i < num; i++) { -+ struct scp_domain *scpd = &scp->domains[i]; -+ struct generic_pm_domain *genpd = &scpd->genpd; - - /* - * Initially turn on all domains to make the domains usable -@@ -507,6 +447,123 @@ static int scpsys_probe(struct platform_ - * valid. - */ - -+ pd_data = &scp->pd_data; -+ -+ ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data); -+ if (ret) -+ dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); -+} -+ -+/* -+ * MT8173 power domain support -+ */ -+ -+static const struct scp_domain_data scp_domain_data_mt8173[] = { -+ [MT8173_POWER_DOMAIN_VDEC] = { -+ .name = "vdec", -+ .sta_mask = PWR_STATUS_VDEC, -+ .ctl_offs = SPM_VDE_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = GENMASK(12, 12), -+ .clk_id = {CLK_MM}, -+ }, -+ [MT8173_POWER_DOMAIN_VENC] = { -+ .name = "venc", -+ .sta_mask = PWR_STATUS_VENC, -+ .ctl_offs = SPM_VEN_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = GENMASK(15, 12), -+ .clk_id = {CLK_MM, CLK_VENC}, -+ }, -+ [MT8173_POWER_DOMAIN_ISP] = { -+ .name = "isp", -+ .sta_mask = PWR_STATUS_ISP, -+ .ctl_offs = SPM_ISP_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = GENMASK(13, 12), -+ .clk_id = {CLK_MM}, -+ }, -+ [MT8173_POWER_DOMAIN_MM] = { -+ .name = "mm", -+ .sta_mask = PWR_STATUS_DISP, -+ .ctl_offs = SPM_DIS_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = GENMASK(12, 12), -+ .clk_id = {CLK_MM}, -+ .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | -+ MT8173_TOP_AXI_PROT_EN_MM_M1, -+ }, -+ [MT8173_POWER_DOMAIN_VENC_LT] = { -+ .name = "venc_lt", -+ .sta_mask = PWR_STATUS_VENC_LT, -+ .ctl_offs = SPM_VEN2_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = GENMASK(15, 12), -+ .clk_id = {CLK_MM, CLK_VENC_LT}, -+ }, -+ [MT8173_POWER_DOMAIN_AUDIO] = { -+ .name = "audio", -+ .sta_mask = PWR_STATUS_AUDIO, -+ .ctl_offs = SPM_AUDIO_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = GENMASK(15, 12), -+ .clk_id = {CLK_NONE}, -+ }, -+ [MT8173_POWER_DOMAIN_USB] = { -+ .name = "usb", -+ .sta_mask = PWR_STATUS_USB, -+ .ctl_offs = SPM_USB_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = GENMASK(15, 12), -+ .clk_id = {CLK_NONE}, -+ .active_wakeup = true, -+ }, -+ [MT8173_POWER_DOMAIN_MFG_ASYNC] = { -+ .name = "mfg_async", -+ .sta_mask = PWR_STATUS_MFG_ASYNC, -+ .ctl_offs = SPM_MFG_ASYNC_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = 0, -+ .clk_id = {CLK_MFG}, -+ }, -+ [MT8173_POWER_DOMAIN_MFG_2D] = { -+ .name = "mfg_2d", -+ .sta_mask = PWR_STATUS_MFG_2D, -+ .ctl_offs = SPM_MFG_2D_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = GENMASK(13, 12), -+ .clk_id = {CLK_NONE}, -+ }, -+ [MT8173_POWER_DOMAIN_MFG] = { -+ .name = "mfg", -+ .sta_mask = PWR_STATUS_MFG, -+ .ctl_offs = SPM_MFG_PWR_CON, -+ .sram_pdn_bits = GENMASK(13, 8), -+ .sram_pdn_ack_bits = GENMASK(21, 16), -+ .clk_id = {CLK_NONE}, -+ .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | -+ MT8173_TOP_AXI_PROT_EN_MFG_M0 | -+ MT8173_TOP_AXI_PROT_EN_MFG_M1 | -+ MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT, -+ }, -+}; -+ -+#define NUM_DOMAINS_MT8173 ARRAY_SIZE(scp_domain_data_mt8173) -+ -+static int __init scpsys_probe_mt8173(struct platform_device *pdev) -+{ -+ struct scp *scp; -+ struct genpd_onecell_data *pd_data; -+ int ret; -+ -+ scp = init_scp(pdev, scp_domain_data_mt8173, NUM_DOMAINS_MT8173); -+ if (IS_ERR(scp)) -+ return PTR_ERR(scp); -+ -+ mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT8173); -+ -+ pd_data = &scp->pd_data; -+ - ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC], - pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]); - if (ret && IS_ENABLED(CONFIG_PM)) -@@ -517,21 +574,36 @@ static int scpsys_probe(struct platform_ - if (ret && IS_ENABLED(CONFIG_PM)) - dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret); - -- ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data); -- if (ret) -- dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret); -- - return 0; - } - -+/* -+ * scpsys driver init -+ */ -+ - static const struct of_device_id of_scpsys_match_tbl[] = { - { - .compatible = "mediatek,mt8173-scpsys", -+ .data = scpsys_probe_mt8173, - }, { - /* sentinel */ - } - }; - -+static int scpsys_probe(struct platform_device *pdev) -+{ -+ int (*probe)(struct platform_device *); -+ const struct of_device_id *of_id; -+ -+ of_id = of_match_node(of_scpsys_match_tbl, pdev->dev.of_node); -+ if (!of_id || !of_id->data) -+ return -EINVAL; -+ -+ probe = of_id->data; -+ -+ return probe(pdev); -+} -+ - static struct platform_driver scpsys_drv = { - .probe = scpsys_probe, - .driver = { diff --git a/target/linux/mediatek/patches-4.9/0009-soc-mediatek-Add-MT2701-scpsys-driver.patch b/target/linux/mediatek/patches-4.9/0009-soc-mediatek-Add-MT2701-scpsys-driver.patch deleted file mode 100644 index 0b47635..0000000 --- a/target/linux/mediatek/patches-4.9/0009-soc-mediatek-Add-MT2701-scpsys-driver.patch +++ /dev/null @@ -1,194 +0,0 @@ -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 09/57] soc: mediatek: Add MT2701 scpsys driver - -Add scpsys driver for MT2701. - -mtk-scpsys now supports MT8173 (arm64) and MT2701 (arm). So it should -be enabled on both arm64 and arm platforms. - -Signed-off-by: Shunli Wang <shunli.wang@mediatek.com> -Signed-off-by: James Liao <jamesjj.liao@mediatek.com> -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 | 108 +++++++++++++++++++++++++++++++++++++- - 2 files changed, 108 insertions(+), 2 deletions(-) - ---- a/drivers/soc/mediatek/Kconfig -+++ b/drivers/soc/mediatek/Kconfig -@@ -23,7 +23,7 @@ config MTK_PMIC_WRAP - config MTK_SCPSYS - bool "MediaTek SCPSYS Support" - depends on ARCH_MEDIATEK || COMPILE_TEST -- default ARM64 && ARCH_MEDIATEK -+ default ARCH_MEDIATEK - select REGMAP - select MTK_INFRACFG - select PM_GENERIC_DOMAINS if PM ---- a/drivers/soc/mediatek/mtk-scpsys.c -+++ b/drivers/soc/mediatek/mtk-scpsys.c -@@ -20,6 +20,7 @@ - #include <linux/regulator/consumer.h> - #include <linux/soc/mediatek/infracfg.h> - -+#include <dt-bindings/power/mt2701-power.h> - #include <dt-bindings/power/mt8173-power.h> - - #define SPM_VDE_PWR_CON 0x0210 -@@ -27,8 +28,13 @@ - #define SPM_VEN_PWR_CON 0x0230 - #define SPM_ISP_PWR_CON 0x0238 - #define SPM_DIS_PWR_CON 0x023c -+#define SPM_CONN_PWR_CON 0x0280 - #define SPM_VEN2_PWR_CON 0x0298 --#define SPM_AUDIO_PWR_CON 0x029c -+#define SPM_AUDIO_PWR_CON 0x029c /* MT8173 */ -+#define SPM_BDP_PWR_CON 0x029c /* MT2701 */ -+#define SPM_ETH_PWR_CON 0x02a0 -+#define SPM_HIF_PWR_CON 0x02a4 -+#define SPM_IFR_MSC_PWR_CON 0x02a8 - #define SPM_MFG_2D_PWR_CON 0x02c0 - #define SPM_MFG_ASYNC_PWR_CON 0x02c4 - #define SPM_USB_PWR_CON 0x02cc -@@ -42,10 +48,15 @@ - #define PWR_ON_2ND_BIT BIT(3) - #define PWR_CLK_DIS_BIT BIT(4) - -+#define PWR_STATUS_CONN BIT(1) - #define PWR_STATUS_DISP BIT(3) - #define PWR_STATUS_MFG BIT(4) - #define PWR_STATUS_ISP BIT(5) - #define PWR_STATUS_VDEC BIT(7) -+#define PWR_STATUS_BDP BIT(14) -+#define PWR_STATUS_ETH BIT(15) -+#define PWR_STATUS_HIF BIT(16) -+#define PWR_STATUS_IFR_MSC BIT(17) - #define PWR_STATUS_VENC_LT BIT(20) - #define PWR_STATUS_VENC BIT(21) - #define PWR_STATUS_MFG_2D BIT(22) -@@ -59,6 +70,7 @@ enum clk_id { - CLK_MFG, - CLK_VENC, - CLK_VENC_LT, -+ CLK_ETHIF, - CLK_MAX, - }; - -@@ -68,6 +80,7 @@ static const char * const clk_names[] = - "mfg", - "venc", - "venc_lt", -+ "ethif", - NULL, - }; - -@@ -455,6 +468,96 @@ static void mtk_register_power_domains(s - } - - /* -+ * MT2701 power domain support -+ */ -+ -+static const struct scp_domain_data scp_domain_data_mt2701[] = { -+ [MT2701_POWER_DOMAIN_CONN] = { -+ .name = "conn", -+ .sta_mask = PWR_STATUS_CONN, -+ .ctl_offs = SPM_CONN_PWR_CON, -+ .bus_prot_mask = 0x0104, -+ .clk_id = {CLK_NONE}, -+ .active_wakeup = true, -+ }, -+ [MT2701_POWER_DOMAIN_DISP] = { -+ .name = "disp", -+ .sta_mask = PWR_STATUS_DISP, -+ .ctl_offs = SPM_DIS_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .clk_id = {CLK_MM}, -+ .bus_prot_mask = 0x0002, -+ .active_wakeup = true, -+ }, -+ [MT2701_POWER_DOMAIN_VDEC] = { -+ .name = "vdec", -+ .sta_mask = PWR_STATUS_VDEC, -+ .ctl_offs = SPM_VDE_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = GENMASK(12, 12), -+ .clk_id = {CLK_MM}, -+ .active_wakeup = true, -+ }, -+ [MT2701_POWER_DOMAIN_ISP] = { -+ .name = "isp", -+ .sta_mask = PWR_STATUS_ISP, -+ .ctl_offs = SPM_ISP_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = GENMASK(13, 12), -+ .clk_id = {CLK_MM}, -+ .active_wakeup = true, -+ }, -+ [MT2701_POWER_DOMAIN_BDP] = { -+ .name = "bdp", -+ .sta_mask = PWR_STATUS_BDP, -+ .ctl_offs = SPM_BDP_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .clk_id = {CLK_NONE}, -+ .active_wakeup = true, -+ }, -+ [MT2701_POWER_DOMAIN_ETH] = { -+ .name = "eth", -+ .sta_mask = PWR_STATUS_ETH, -+ .ctl_offs = SPM_ETH_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = GENMASK(15, 12), -+ .clk_id = {CLK_ETHIF}, -+ .active_wakeup = true, -+ }, -+ [MT2701_POWER_DOMAIN_HIF] = { -+ .name = "hif", -+ .sta_mask = PWR_STATUS_HIF, -+ .ctl_offs = SPM_HIF_PWR_CON, -+ .sram_pdn_bits = GENMASK(11, 8), -+ .sram_pdn_ack_bits = GENMASK(15, 12), -+ .clk_id = {CLK_ETHIF}, -+ .active_wakeup = true, -+ }, -+ [MT2701_POWER_DOMAIN_IFR_MSC] = { -+ .name = "ifr_msc", -+ .sta_mask = PWR_STATUS_IFR_MSC, -+ .ctl_offs = SPM_IFR_MSC_PWR_CON, -+ .clk_id = {CLK_NONE}, -+ .active_wakeup = true, -+ }, -+}; -+ -+#define NUM_DOMAINS_MT2701 ARRAY_SIZE(scp_domain_data_mt2701) -+ -+static int __init scpsys_probe_mt2701(struct platform_device *pdev) -+{ -+ struct scp *scp; -+ -+ scp = init_scp(pdev, scp_domain_data_mt2701, NUM_DOMAINS_MT2701); -+ if (IS_ERR(scp)) -+ return PTR_ERR(scp); -+ -+ mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT2701); -+ -+ return 0; -+} -+ -+/* - * MT8173 power domain support - */ - -@@ -583,6 +686,9 @@ static int __init scpsys_probe_mt8173(st - - static const struct of_device_id of_scpsys_match_tbl[] = { - { -+ .compatible = "mediatek,mt2701-scpsys", -+ .data = scpsys_probe_mt2701, -+ }, { - .compatible = "mediatek,mt8173-scpsys", - .data = scpsys_probe_mt8173, - }, { diff --git a/target/linux/mediatek/patches-4.9/0010-clk-add-hifsys-reset.patch b/target/linux/mediatek/patches-4.9/0010-clk-add-hifsys-reset.patch deleted file mode 100644 index a7ebb06..0000000 --- a/target/linux/mediatek/patches-4.9/0010-clk-add-hifsys-reset.patch +++ /dev/null @@ -1,30 +0,0 @@ -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 10/57] clk: add hifsys reset - -Hi, - -small patch to add hifsys reset bits. Maybe you could add it to the next -version of your patch series. i have teste scpsys and clk on mt7623 today -and it works well. - -thanks, - John - -Signed-off-by: John Crispin <blogic@openwrt.org> ---- - 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 -@@ -1000,6 +1000,8 @@ static void __init mtk_hifsys_init(struc - if (r) - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); -+ -+ mtk_register_reset_controller(node, 1, 0x34); - } - CLK_OF_DECLARE(mtk_hifsys, "mediatek,mt2701-hifsys", mtk_hifsys_init); - diff --git a/target/linux/mediatek/patches-4.9/0011-scpsys-various-fixes.patch b/target/linux/mediatek/patches-4.9/0011-scpsys-various-fixes.patch deleted file mode 100644 index 8a9da5e..0000000 --- a/target/linux/mediatek/patches-4.9/0011-scpsys-various-fixes.patch +++ /dev/null @@ -1,20 +0,0 @@ -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 11/57] scpsys: various fixes - ---- - 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 -@@ -1043,6 +1043,8 @@ static void __init mtk_ethsys_init(struc - if (r) - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); -+ -+ mtk_register_reset_controller(node, 1, 0x34); - } - CLK_OF_DECLARE(mtk_ethsys, "mediatek,mt2701-ethsys", mtk_ethsys_init); - diff --git a/target/linux/mediatek/patches-4.9/0012-clk-dont-disable-unused-clocks.patch b/target/linux/mediatek/patches-4.9/0012-clk-dont-disable-unused-clocks.patch deleted file mode 100644 index ed4111d..0000000 --- a/target/linux/mediatek/patches-4.9/0012-clk-dont-disable-unused-clocks.patch +++ /dev/null @@ -1,21 +0,0 @@ -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 12/57] clk: dont disable unused clocks - -Signed-off-by: John Crispin <blogic@openwrt.org> ---- - drivers/clk/clk.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/clk/clk.c -+++ b/drivers/clk/clk.c -@@ -796,7 +796,7 @@ unlock_out: - clk_core_disable_unprepare(core->parent); - } - --static bool clk_ignore_unused; -+static bool clk_ignore_unused = true; - static int __init clk_ignore_unused_setup(char *__unused) - { - clk_ignore_unused = true; diff --git a/target/linux/mediatek/patches-4.9/0013-clk-mediatek-enable-critical-clocks.patch b/target/linux/mediatek/patches-4.9/0013-clk-mediatek-enable-critical-clocks.patch deleted file mode 100644 index 26257bd..0000000 --- a/target/linux/mediatek/patches-4.9/0013-clk-mediatek-enable-critical-clocks.patch +++ /dev/null @@ -1,69 +0,0 @@ -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 13/57] clk: mediatek: enable critical clocks - -Signed-off-by: John Crispin <blogic@openwrt.org> ---- - drivers/clk/mediatek/clk-mt2701.c | 22 ++++++++++++++++++++-- - 1 file changed, 20 insertions(+), 2 deletions(-) - ---- a/drivers/clk/mediatek/clk-mt2701.c -+++ b/drivers/clk/mediatek/clk-mt2701.c -@@ -573,6 +573,20 @@ static const struct mtk_gate top_clks[] - GATE_TOP_AUD(CLK_TOP_AUD_I2S6_MCLK, "aud_i2s6_mclk", "aud_k6_src_div", 28), - }; - -+static struct clk_onecell_data *mt7623_top_clk_data __initdata; -+static struct clk_onecell_data *mt7623_pll_clk_data __initdata; -+ -+static void __init mtk_clk_enable_critical(void) -+{ -+ if (!mt7623_top_clk_data || !mt7623_pll_clk_data) -+ return; -+ -+ clk_prepare_enable(mt7623_pll_clk_data->clks[CLK_APMIXED_ARMPLL]); -+ clk_prepare_enable(mt7623_top_clk_data->clks[CLK_TOP_MEM_SEL]); -+ clk_prepare_enable(mt7623_top_clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]); -+ clk_prepare_enable(mt7623_top_clk_data->clks[CLK_TOP_RTC_SEL]); -+} -+ - static void __init mtk_topckgen_init(struct device_node *node) - { - struct clk_onecell_data *clk_data; -@@ -585,7 +599,7 @@ static void __init mtk_topckgen_init(str - return; - } - -- clk_data = mtk_alloc_clk_data(CLK_TOP_NR); -+ mt7623_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR); - - mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), - clk_data); -@@ -606,6 +620,8 @@ static void __init mtk_topckgen_init(str - if (r) - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); -+ -+ mtk_clk_enable_critical(); - } - CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt2701-topckgen", mtk_topckgen_init); - -@@ -1202,7 +1218,7 @@ static void __init mtk_apmixedsys_init(s - struct clk_onecell_data *clk_data; - int r; - -- clk_data = mtk_alloc_clk_data(ARRAY_SIZE(apmixed_plls)); -+ mt7623_pll_clk_data = clk_data = mtk_alloc_clk_data(ARRAY_SIZE(apmixed_plls)); - if (!clk_data) - return; - -@@ -1213,6 +1229,8 @@ static void __init mtk_apmixedsys_init(s - if (r) - pr_err("%s(): could not register clock provider: %d\n", - __func__, r); -+ -+ mtk_clk_enable_critical(); - } - CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt2701-apmixedsys", - mtk_apmixedsys_init); diff --git a/target/linux/mediatek/patches-4.9/0014-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 deleted file mode 100644 index 7e19c6f..0000000 --- a/target/linux/mediatek/patches-4.9/0014-clk-mediatek-Export-CPU-mux-clocks-for-CPU-frequency.patch +++ /dev/null @@ -1,287 +0,0 @@ -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 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 +- - 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 - ---- a/drivers/clk/mediatek/Makefile -+++ b/drivers/clk/mediatek/Makefile -@@ -1,4 +1,4 @@ --obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o -+obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o - obj-$(CONFIG_RESET_CONTROLLER) += reset.o - obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o - obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o ---- /dev/null -+++ b/drivers/clk/mediatek/clk-cpumux.c -@@ -0,0 +1,127 @@ -+/* -+ * Copyright (c) 2015 Linaro Ltd. -+ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * 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-provider.h> -+#include <linux/mfd/syscon.h> -+#include <linux/slab.h> -+ -+#include "clk-mtk.h" -+#include "clk-cpumux.h" -+ -+struct mtk_clk_cpumux { -+ struct clk_hw hw; -+ struct regmap *regmap; -+ u32 reg; -+ u32 mask; -+ u8 shift; -+}; -+ -+static inline struct mtk_clk_cpumux *to_mtk_clk_mux(struct clk_hw *_hw) -+{ -+ return container_of(_hw, struct mtk_clk_cpumux, hw); -+} -+ -+static u8 clk_cpumux_get_parent(struct clk_hw *hw) -+{ -+ struct mtk_clk_cpumux *mux = to_mtk_clk_mux(hw); -+ int num_parents = clk_hw_get_num_parents(hw); -+ unsigned int val; -+ -+ regmap_read(mux->regmap, mux->reg, &val); -+ -+ val >>= mux->shift; -+ val &= mux->mask; -+ -+ if (val >= num_parents) -+ return -EINVAL; -+ -+ return val; -+} -+ -+static int clk_cpumux_set_parent(struct clk_hw *hw, u8 index) -+{ -+ struct mtk_clk_cpumux *mux = to_mtk_clk_mux(hw); -+ u32 mask, val; -+ -+ val = index << mux->shift; -+ mask = mux->mask << mux->shift; -+ -+ return regmap_update_bits(mux->regmap, mux->reg, mask, val); -+} -+ -+static const struct clk_ops clk_cpumux_ops = { -+ .get_parent = clk_cpumux_get_parent, -+ .set_parent = clk_cpumux_set_parent, -+}; -+ -+static struct clk __init *mtk_clk_register_cpumux(const struct mtk_composite *mux, -+ struct regmap *regmap) -+{ -+ struct mtk_clk_cpumux *cpumux; -+ struct clk *clk; -+ struct clk_init_data init; -+ -+ cpumux = kzalloc(sizeof(*cpumux), GFP_KERNEL); -+ if (!cpumux) -+ return ERR_PTR(-ENOMEM); -+ -+ init.name = mux->name; -+ init.ops = &clk_cpumux_ops; -+ init.parent_names = mux->parent_names; -+ init.num_parents = mux->num_parents; -+ init.flags = mux->flags; -+ -+ cpumux->reg = mux->mux_reg; -+ cpumux->shift = mux->mux_shift; -+ cpumux->mask = BIT(mux->mux_width) - 1; -+ cpumux->regmap = regmap; -+ cpumux->hw.init = &init; -+ -+ clk = clk_register(NULL, &cpumux->hw); -+ if (IS_ERR(clk)) -+ kfree(cpumux); -+ -+ return clk; -+} -+ -+int __init mtk_clk_register_cpumuxes(struct device_node *node, -+ const struct mtk_composite *clks, int num, -+ struct clk_onecell_data *clk_data) -+{ -+ int i; -+ struct clk *clk; -+ struct regmap *regmap; -+ -+ regmap = syscon_node_to_regmap(node); -+ if (IS_ERR(regmap)) { -+ pr_err("Cannot find regmap for %s: %ld\n", node->full_name, -+ PTR_ERR(regmap)); -+ return PTR_ERR(regmap); -+ } -+ -+ for (i = 0; i < num; i++) { -+ const struct mtk_composite *mux = &clks[i]; -+ -+ clk = mtk_clk_register_cpumux(mux, regmap); -+ if (IS_ERR(clk)) { -+ pr_err("Failed to register clk %s: %ld\n", -+ mux->name, PTR_ERR(clk)); -+ continue; -+ } -+ -+ clk_data->clks[mux->id] = clk; -+ } -+ -+ return 0; -+} ---- /dev/null -+++ b/drivers/clk/mediatek/clk-cpumux.h -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (c) 2015 Linaro Ltd. -+ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * 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. -+ */ -+ -+#ifndef __DRV_CLK_CPUMUX_H -+#define __DRV_CLK_CPUMUX_H -+ -+int mtk_clk_register_cpumuxes(struct device_node *node, -+ const struct mtk_composite *clks, int num, -+ struct clk_onecell_data *clk_data); -+ -+#endif /* __DRV_CLK_CPUMUX_H */ ---- a/drivers/clk/mediatek/clk-mt2701.c -+++ b/drivers/clk/mediatek/clk-mt2701.c -@@ -18,6 +18,7 @@ - - #include "clk-mtk.h" - #include "clk-gate.h" -+#include "clk-cpumux.h" - - #include <dt-bindings/clock/mt2701-clk.h> - -@@ -465,6 +466,10 @@ static const char * const cpu_parents[] - "mmpll" - }; - -+static const struct mtk_composite cpu_muxes[] __initconst = { -+ MUX(CLK_INFRA_CPUSEL, "infra_cpu_sel", cpu_parents, 0x0000, 2, 2), -+}; -+ - static const struct mtk_composite top_muxes[] __initconst = { - MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, - 0x0040, 0, 3, INVALID_MUX_GATE_BIT), -@@ -677,6 +682,9 @@ static void __init mtk_infrasys_init(str - mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), - clk_data); - -+ mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), -+ clk_data); -+ - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) - pr_err("%s(): could not register clock provider: %d\n", ---- a/drivers/clk/mediatek/clk-mt8173.c -+++ b/drivers/clk/mediatek/clk-mt8173.c -@@ -18,6 +18,7 @@ - - #include "clk-mtk.h" - #include "clk-gate.h" -+#include "clk-cpumux.h" - - #include <dt-bindings/clock/mt8173-clk.h> - -@@ -525,6 +526,25 @@ static const char * const i2s3_b_ck_pare - "apll2_div5" - }; - -+static const char * const ca53_parents[] __initconst = { -+ "clk26m", -+ "armca7pll", -+ "mainpll", -+ "univpll" -+}; -+ -+static const char * const ca57_parents[] __initconst = { -+ "clk26m", -+ "armca15pll", -+ "mainpll", -+ "univpll" -+}; -+ -+static const struct mtk_composite cpu_muxes[] __initconst = { -+ MUX(CLK_INFRA_CA53SEL, "infra_ca53_sel", ca53_parents, 0x0000, 0, 2), -+ MUX(CLK_INFRA_CA57SEL, "infra_ca57_sel", ca57_parents, 0x0000, 2, 2), -+}; -+ - static const struct mtk_composite top_muxes[] __initconst = { - /* CLK_CFG_0 */ - MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3), -@@ -948,6 +968,9 @@ static void __init mtk_infrasys_init(str - clk_data); - mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); - -+ mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), -+ clk_data); -+ - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) - pr_err("%s(): could not register clock provider: %d\n", ---- a/include/dt-bindings/clock/mt2701-clk.h -+++ b/include/dt-bindings/clock/mt2701-clk.h -@@ -221,7 +221,8 @@ - #define CLK_INFRA_PMICWRAP 17 - #define CLK_INFRA_DDCCI 18 - #define CLK_INFRA_CLK_13M 19 --#define CLK_INFRA_NR 20 -+#define CLK_INFRA_CPUSEL 20 -+#define CLK_INFRA_NR 21 - - /* PERICFG */ - ---- a/include/dt-bindings/clock/mt8173-clk.h -+++ b/include/dt-bindings/clock/mt8173-clk.h -@@ -193,7 +193,9 @@ - #define CLK_INFRA_PMICSPI 10 - #define CLK_INFRA_PMICWRAP 11 - #define CLK_INFRA_CLK_13M 12 --#define CLK_INFRA_NR_CLK 13 -+#define CLK_INFRA_CA53SEL 13 -+#define CLK_INFRA_CA57SEL 14 -+#define CLK_INFRA_NR_CLK 15 - - /* PERI_SYS */ - diff --git a/target/linux/mediatek/patches-4.9/0015-cpufreq-mediatek-add-driver.patch b/target/linux/mediatek/patches-4.9/0015-cpufreq-mediatek-add-driver.patch deleted file mode 100644 index af60025..0000000 --- a/target/linux/mediatek/patches-4.9/0015-cpufreq-mediatek-add-driver.patch +++ /dev/null @@ -1,433 +0,0 @@ -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 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 +++++++++++++++++++++++++++++++++++++++ - 3 files changed, 399 insertions(+) - create mode 100644 drivers/cpufreq/mt7623-cpufreq.c - ---- a/drivers/cpufreq/Kconfig.arm -+++ b/drivers/cpufreq/Kconfig.arm -@@ -74,6 +74,15 @@ config ARM_KIRKWOOD_CPUFREQ - This adds the CPUFreq driver for Marvell Kirkwood - SoCs. - -+config ARM_MT7623_CPUFREQ -+ bool "Mediatek MT7623 CPUFreq support" -+ depends on ARCH_MEDIATEK && REGULATOR -+ depends on ARM || (ARM_CPU_TOPOLOGY && COMPILE_TEST) -+ depends on !CPU_THERMAL || THERMAL=y -+ select PM_OPP -+ help -+ This adds the CPUFreq driver support for Mediatek MT7623 SoC. -+ - config ARM_MT8173_CPUFREQ - tristate "Mediatek MT8173 CPUFreq support" - depends on ARCH_MEDIATEK && REGULATOR ---- a/drivers/cpufreq/Makefile -+++ b/drivers/cpufreq/Makefile -@@ -58,6 +58,7 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += hi - obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o - obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o - obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o -+obj-$(CONFIG_ARM_MT7623_CPUFREQ) += mt7623-cpufreq.o - obj-$(CONFIG_ARM_MT8173_CPUFREQ) += mt8173-cpufreq.o - obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o - obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o ---- /dev/null -+++ b/drivers/cpufreq/mt7623-cpufreq.c -@@ -0,0 +1,389 @@ -+/* -+ * Copyright (c) 2015 Linaro Ltd. -+ * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * 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/cpu.h> -+#include <linux/cpu_cooling.h> -+#include <linux/cpufreq.h> -+#include <linux/cpumask.h> -+#include <linux/of.h> -+#include <linux/platform_device.h> -+#include <linux/pm_opp.h> -+#include <linux/regulator/consumer.h> -+#include <linux/slab.h> -+#include <linux/thermal.h> -+ -+#define VOLT_TOL (10000) -+ -+/* -+ * When scaling the clock frequency of a CPU clock domain, the clock source -+ * needs to be switched to another stable PLL clock temporarily until -+ * the original PLL becomes stable at target frequency. -+ */ -+struct mtk_cpu_dvfs_info { -+ struct device *cpu_dev; -+ struct regulator *proc_reg; -+ struct clk *cpu_clk; -+ struct clk *inter_clk; -+ struct thermal_cooling_device *cdev; -+ int intermediate_voltage; -+}; -+ -+static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc) -+{ -+ return regulator_set_voltage(info->proc_reg, vproc, -+ vproc + VOLT_TOL); -+} -+ -+static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, -+ unsigned int index) -+{ -+ struct cpufreq_frequency_table *freq_table = policy->freq_table; -+ struct clk *cpu_clk = policy->clk; -+ struct clk *armpll = clk_get_parent(cpu_clk); -+ struct mtk_cpu_dvfs_info *info = policy->driver_data; -+ struct device *cpu_dev = info->cpu_dev; -+ struct dev_pm_opp *opp; -+ long freq_hz, old_freq_hz; -+ int vproc, old_vproc, inter_vproc, target_vproc, ret; -+ -+ inter_vproc = info->intermediate_voltage; -+ -+ old_freq_hz = clk_get_rate(cpu_clk); -+ old_vproc = regulator_get_voltage(info->proc_reg); -+ -+ freq_hz = freq_table[index].frequency * 1000; -+ -+ rcu_read_lock(); -+ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); -+ if (IS_ERR(opp)) { -+ rcu_read_unlock(); -+ pr_err("cpu%d: failed to find OPP for %ld\n", -+ policy->cpu, freq_hz); -+ return PTR_ERR(opp); -+ } -+ vproc = dev_pm_opp_get_voltage(opp); -+ rcu_read_unlock(); -+ -+ /* -+ * If the new voltage or the intermediate voltage is higher than the -+ * current voltage, scale up voltage first. -+ */ -+ target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc; -+ if (old_vproc < target_vproc) { -+ ret = mtk_cpufreq_set_voltage(info, target_vproc); -+ if (ret) { -+ pr_err("cpu%d: failed to scale up voltage!\n", -+ policy->cpu); -+ mtk_cpufreq_set_voltage(info, old_vproc); -+ return ret; -+ } -+ } -+ -+ /* Reparent the CPU clock to intermediate clock. */ -+ ret = clk_set_parent(cpu_clk, info->inter_clk); -+ if (ret) { -+ pr_err("cpu%d: failed to re-parent cpu clock!\n", -+ policy->cpu); -+ mtk_cpufreq_set_voltage(info, old_vproc); -+ WARN_ON(1); -+ return ret; -+ } -+ -+ /* Set the original PLL to target rate. */ -+ ret = clk_set_rate(armpll, freq_hz); -+ if (ret) { -+ pr_err("cpu%d: failed to scale cpu clock rate!\n", -+ policy->cpu); -+ clk_set_parent(cpu_clk, armpll); -+ mtk_cpufreq_set_voltage(info, old_vproc); -+ return ret; -+ } -+ -+ /* Set parent of CPU clock back to the original PLL. */ -+ ret = clk_set_parent(cpu_clk, armpll); -+ if (ret) { -+ pr_err("cpu%d: failed to re-parent cpu clock!\n", -+ policy->cpu); -+ mtk_cpufreq_set_voltage(info, inter_vproc); -+ WARN_ON(1); -+ return ret; -+ } -+ -+ /* -+ * If the new voltage is lower than the intermediate voltage or the -+ * original voltage, scale down to the new voltage. -+ */ -+ if (vproc < inter_vproc || vproc < old_vproc) { -+ ret = mtk_cpufreq_set_voltage(info, vproc); -+ if (ret) { -+ pr_err("cpu%d: failed to scale down voltage!\n", -+ policy->cpu); -+ clk_set_parent(cpu_clk, info->inter_clk); -+ clk_set_rate(armpll, old_freq_hz); -+ clk_set_parent(cpu_clk, armpll); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static void mtk_cpufreq_ready(struct cpufreq_policy *policy) -+{ -+ struct mtk_cpu_dvfs_info *info = policy->driver_data; -+ struct device_node *np = of_node_get(info->cpu_dev->of_node); -+ -+ if (WARN_ON(!np)) -+ return; -+ -+ if (of_find_property(np, "#cooling-cells", NULL)) { -+ info->cdev = of_cpufreq_cooling_register(np, -+ policy->related_cpus); -+ -+ if (IS_ERR(info->cdev)) { -+ dev_err(info->cpu_dev, -+ "running cpufreq without cooling device: %ld\n", -+ PTR_ERR(info->cdev)); -+ -+ info->cdev = NULL; -+ } -+ } -+ -+ of_node_put(np); -+} -+ -+static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) -+{ -+ struct device *cpu_dev; -+ struct regulator *proc_reg = ERR_PTR(-ENODEV); -+ struct clk *cpu_clk = ERR_PTR(-ENODEV); -+ struct clk *inter_clk = ERR_PTR(-ENODEV); -+ struct dev_pm_opp *opp; -+ unsigned long rate; -+ int ret; -+ -+ cpu_dev = get_cpu_device(cpu); -+ if (!cpu_dev) { -+ pr_err("failed to get cpu%d device\n", cpu); -+ return -ENODEV; -+ } -+ -+ cpu_clk = clk_get(cpu_dev, "cpu"); -+ if (IS_ERR(cpu_clk)) { -+ if (PTR_ERR(cpu_clk) == -EPROBE_DEFER) -+ pr_warn("cpu clk for cpu%d not ready, retry.\n", cpu); -+ else -+ pr_err("failed to get cpu clk for cpu%d\n", cpu); -+ -+ ret = PTR_ERR(cpu_clk); -+ return ret; -+ } -+ -+ inter_clk = clk_get(cpu_dev, "intermediate"); -+ if (IS_ERR(inter_clk)) { -+ if (PTR_ERR(inter_clk) == -EPROBE_DEFER) -+ pr_warn("intermediate clk for cpu%d not ready, retry.\n", -+ cpu); -+ else -+ pr_err("failed to get intermediate clk for cpu%d\n", -+ cpu); -+ -+ ret = PTR_ERR(inter_clk); -+ goto out_free_resources; -+ } -+ -+ proc_reg = regulator_get_exclusive(cpu_dev, "proc"); -+ if (IS_ERR(proc_reg)) { -+ if (PTR_ERR(proc_reg) == -EPROBE_DEFER) -+ pr_warn("proc regulator for cpu%d not ready, retry.\n", -+ cpu); -+ else -+ pr_err("failed to get proc regulator for cpu%d\n", -+ cpu); -+ -+ ret = PTR_ERR(proc_reg); -+ goto out_free_resources; -+ } -+ -+ ret = dev_pm_opp_of_add_table(cpu_dev); -+ if (ret) { -+ pr_warn("no OPP table for cpu%d\n", cpu); -+ goto out_free_resources; -+ } -+ -+ /* Search a safe voltage for intermediate frequency. */ -+ rate = clk_get_rate(inter_clk); -+ rcu_read_lock(); -+ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate); -+ if (IS_ERR(opp)) { -+ rcu_read_unlock(); -+ pr_err("failed to get intermediate opp for cpu%d\n", cpu); -+ ret = PTR_ERR(opp); -+ goto out_free_opp_table; -+ } -+ info->intermediate_voltage = dev_pm_opp_get_voltage(opp); -+ rcu_read_unlock(); -+ -+ info->cpu_dev = cpu_dev; -+ info->proc_reg = proc_reg; -+ info->cpu_clk = cpu_clk; -+ info->inter_clk = inter_clk; -+ -+ return 0; -+ -+out_free_opp_table: -+ dev_pm_opp_of_remove_table(cpu_dev); -+ -+out_free_resources: -+ if (!IS_ERR(proc_reg)) -+ regulator_put(proc_reg); -+ if (!IS_ERR(cpu_clk)) -+ clk_put(cpu_clk); -+ if (!IS_ERR(inter_clk)) -+ clk_put(inter_clk); -+ -+ return ret; -+} -+ -+static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info) -+{ -+ if (!IS_ERR(info->proc_reg)) -+ regulator_put(info->proc_reg); -+ if (!IS_ERR(info->cpu_clk)) -+ clk_put(info->cpu_clk); -+ if (!IS_ERR(info->inter_clk)) -+ clk_put(info->inter_clk); -+ -+ dev_pm_opp_of_remove_table(info->cpu_dev); -+} -+ -+static int mtk_cpufreq_init(struct cpufreq_policy *policy) -+{ -+ struct mtk_cpu_dvfs_info *info; -+ struct cpufreq_frequency_table *freq_table; -+ int ret; -+ -+ info = kzalloc(sizeof(*info), GFP_KERNEL); -+ if (!info) -+ return -ENOMEM; -+ -+ ret = mtk_cpu_dvfs_info_init(info, policy->cpu); -+ if (ret) { -+ pr_err("%s failed to initialize dvfs info for cpu%d\n", -+ __func__, policy->cpu); -+ goto out_free_dvfs_info; -+ } -+ -+ ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table); -+ if (ret) { -+ pr_err("failed to init cpufreq table for cpu%d: %d\n", -+ policy->cpu, ret); -+ goto out_release_dvfs_info; -+ } -+ -+ ret = cpufreq_table_validate_and_show(policy, freq_table); -+ if (ret) { -+ pr_err("%s: invalid frequency table: %d\n", __func__, ret); -+ goto out_free_cpufreq_table; -+ } -+ -+ /* CPUs in the same cluster share a clock and power domain. */ -+ cpumask_setall(policy->cpus); -+ policy->driver_data = info; -+ policy->clk = info->cpu_clk; -+ -+ return 0; -+ -+out_free_cpufreq_table: -+ dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table); -+ -+out_release_dvfs_info: -+ mtk_cpu_dvfs_info_release(info); -+ -+out_free_dvfs_info: -+ kfree(info); -+ -+ return ret; -+} -+ -+static int mtk_cpufreq_exit(struct cpufreq_policy *policy) -+{ -+ struct mtk_cpu_dvfs_info *info = policy->driver_data; -+ -+ cpufreq_cooling_unregister(info->cdev); -+ dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table); -+ mtk_cpu_dvfs_info_release(info); -+ kfree(info); -+ -+ return 0; -+} -+ -+static struct cpufreq_driver mt7623_cpufreq_driver = { -+ .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, -+ .verify = cpufreq_generic_frequency_table_verify, -+ .target_index = mtk_cpufreq_set_target, -+ .get = cpufreq_generic_get, -+ .init = mtk_cpufreq_init, -+ .exit = mtk_cpufreq_exit, -+ .ready = mtk_cpufreq_ready, -+ .name = "mtk-cpufreq", -+ .attr = cpufreq_generic_attr, -+}; -+ -+static int mt7623_cpufreq_probe(struct platform_device *pdev) -+{ -+ int ret; -+ -+ ret = cpufreq_register_driver(&mt7623_cpufreq_driver); -+ if (ret) -+ pr_err("failed to register mtk cpufreq driver\n"); -+ -+ return ret; -+} -+ -+static struct platform_driver mt7623_cpufreq_platdrv = { -+ .driver = { -+ .name = "mt7623-cpufreq", -+ }, -+ .probe = mt7623_cpufreq_probe, -+}; -+ -+static int mt7623_cpufreq_driver_init(void) -+{ -+ struct platform_device *pdev; -+ int err; -+ -+ if (!of_machine_is_compatible("mediatek,mt7623")) -+ return -ENODEV; -+ -+ err = platform_driver_register(&mt7623_cpufreq_platdrv); -+ if (err) -+ return err; -+ -+ /* -+ * Since there's no place to hold device registration code and no -+ * device tree based way to match cpufreq driver yet, both the driver -+ * and the device registration codes are put here to handle defer -+ * probing. -+ */ -+ pdev = platform_device_register_simple("mt7623-cpufreq", -1, NULL, 0); -+ if (IS_ERR(pdev)) { -+ pr_err("failed to register mtk-cpufreq platform device\n"); -+ return PTR_ERR(pdev); -+ } -+ -+ return 0; -+} -+device_initcall(mt7623_cpufreq_driver_init); diff --git a/target/linux/mediatek/patches-4.9/0016-pwm-add-pwm-mediatek.patch b/target/linux/mediatek/patches-4.9/0016-pwm-add-pwm-mediatek.patch deleted file mode 100644 index 2e8414e..0000000 --- a/target/linux/mediatek/patches-4.9/0016-pwm-add-pwm-mediatek.patch +++ /dev/null @@ -1,274 +0,0 @@ -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 16/57] pwm: add pwm-mediatek - -Signed-off-by: John Crispin <john@phrozen.org> ---- - 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 -+++ b/drivers/pwm/Kconfig -@@ -282,6 +282,15 @@ config PWM_MTK_DISP - To compile this driver as a module, choose M here: the module - will be called pwm-mtk-disp. - -+config PWM_MEDIATEK -+ tristate "MediaTek PWM support" -+ depends on ARCH_MEDIATEK || COMPILE_TEST -+ help -+ Generic PWM framework driver for Mediatek ARM SoC. -+ -+ To compile this driver as a module, choose M here: the module -+ will be called pwm-mxs. -+ - config PWM_MXS - tristate "Freescale MXS PWM support" - depends on ARCH_MXS && OF ---- a/drivers/pwm/Makefile -+++ b/drivers/pwm/Makefile -@@ -25,6 +25,7 @@ obj-$(CONFIG_PWM_LPSS) += pwm-lpss.o - obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-pci.o - obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o - obj-$(CONFIG_PWM_MESON) += pwm-meson.o -+obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o - obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o - obj-$(CONFIG_PWM_MXS) += pwm-mxs.o - obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o ---- /dev/null -+++ b/drivers/pwm/pwm-mediatek.c -@@ -0,0 +1,230 @@ -+/* -+ * Mediatek Pulse Width Modulator driver -+ * -+ * Copyright (C) 2015 John Crispin <blogic@openwrt.org> -+ * -+ * This file is licensed under the terms of the GNU General Public -+ * License version 2. This program is licensed "as is" without any -+ * warranty of any kind, whether express or implied. -+ */ -+ -+#include <linux/err.h> -+#include <linux/io.h> -+#include <linux/ioport.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/clk.h> -+#include <linux/of.h> -+#include <linux/platform_device.h> -+#include <linux/pwm.h> -+#include <linux/slab.h> -+#include <linux/types.h> -+ -+#define NUM_PWM 5 -+ -+/* PWM registers and bits definitions */ -+#define PWMCON 0x00 -+#define PWMHDUR 0x04 -+#define PWMLDUR 0x08 -+#define PWMGDUR 0x0c -+#define PWMWAVENUM 0x28 -+#define PWMDWIDTH 0x2c -+#define PWMTHRES 0x30 -+ -+/** -+ * struct mtk_pwm_chip - struct representing pwm chip -+ * -+ * @mmio_base: base address of pwm chip -+ * @chip: linux pwm chip representation -+ */ -+struct mtk_pwm_chip { -+ void __iomem *mmio_base; -+ struct pwm_chip chip; -+ struct clk *clk_top; -+ struct clk *clk_main; -+ struct clk *clk_pwm[NUM_PWM]; -+}; -+ -+static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip) -+{ -+ return container_of(chip, struct mtk_pwm_chip, chip); -+} -+ -+static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num, -+ unsigned long offset) -+{ -+ return ioread32(chip->mmio_base + 0x10 + (num * 0x40) + offset); -+} -+ -+static inline void mtk_pwm_writel(struct mtk_pwm_chip *chip, -+ unsigned int num, unsigned long offset, -+ unsigned long val) -+{ -+ iowrite32(val, chip->mmio_base + 0x10 + (num * 0x40) + offset); -+} -+ -+static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, -+ int duty_ns, int period_ns) -+{ -+ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); -+ u32 resolution = 100 / 4; -+ u32 clkdiv = 0; -+ -+ resolution = 1000000000 / (clk_get_rate(pc->clk_pwm[pwm->hwpwm])); -+ -+ while (period_ns / resolution > 8191) { -+ clkdiv++; -+ resolution *= 2; -+ } -+ -+ if (clkdiv > 7) -+ return -1; -+ -+ mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | BIT(3) | clkdiv); -+ mtk_pwm_writel(pc, pwm->hwpwm, PWMDWIDTH, period_ns / resolution); -+ mtk_pwm_writel(pc, pwm->hwpwm, PWMTHRES, duty_ns / resolution); -+ return 0; -+} -+ -+static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) -+{ -+ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); -+ u32 val; -+ int ret; -+ -+ ret = clk_prepare(pc->clk_pwm[pwm->hwpwm]); -+ if (ret < 0) -+ return ret; -+ -+ val = ioread32(pc->mmio_base); -+ val |= BIT(pwm->hwpwm); -+ iowrite32(val, pc->mmio_base); -+ -+ return 0; -+} -+ -+static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) -+{ -+ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); -+ u32 val; -+ -+ val = ioread32(pc->mmio_base); -+ val &= ~BIT(pwm->hwpwm); -+ iowrite32(val, pc->mmio_base); -+ clk_unprepare(pc->clk_pwm[pwm->hwpwm]); -+} -+ -+static const struct pwm_ops mtk_pwm_ops = { -+ .config = mtk_pwm_config, -+ .enable = mtk_pwm_enable, -+ .disable = mtk_pwm_disable, -+ .owner = THIS_MODULE, -+}; -+ -+static int mtk_pwm_probe(struct platform_device *pdev) -+{ -+ struct mtk_pwm_chip *pc; -+ struct resource *r; -+ int ret; -+ -+ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); -+ if (!pc) -+ return -ENOMEM; -+ -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ pc->mmio_base = devm_ioremap_resource(&pdev->dev, r); -+ if (IS_ERR(pc->mmio_base)) -+ return PTR_ERR(pc->mmio_base); -+ -+ pc->clk_main = devm_clk_get(&pdev->dev, "main"); -+ if (IS_ERR(pc->clk_main)) -+ return PTR_ERR(pc->clk_main); -+ -+ pc->clk_top = devm_clk_get(&pdev->dev, "top"); -+ if (IS_ERR(pc->clk_top)) -+ return PTR_ERR(pc->clk_top); -+ -+ pc->clk_pwm[0] = devm_clk_get(&pdev->dev, "pwm1"); -+ if (IS_ERR(pc->clk_pwm[0])) -+ return PTR_ERR(pc->clk_pwm[0]); -+ -+ pc->clk_pwm[1] = devm_clk_get(&pdev->dev, "pwm2"); -+ if (IS_ERR(pc->clk_pwm[1])) -+ return PTR_ERR(pc->clk_pwm[1]); -+ -+ pc->clk_pwm[2] = devm_clk_get(&pdev->dev, "pwm3"); -+ if (IS_ERR(pc->clk_pwm[2])) -+ return PTR_ERR(pc->clk_pwm[2]); -+ -+ pc->clk_pwm[3] = devm_clk_get(&pdev->dev, "pwm4"); -+ if (IS_ERR(pc->clk_pwm[3])) -+ return PTR_ERR(pc->clk_pwm[3]); -+ -+ pc->clk_pwm[4] = devm_clk_get(&pdev->dev, "pwm5"); -+ if (IS_ERR(pc->clk_pwm[4])) -+ return PTR_ERR(pc->clk_pwm[4]); -+ -+ ret = clk_prepare(pc->clk_top); -+ if (ret < 0) -+ return ret; -+ -+ ret = clk_prepare(pc->clk_main); -+ if (ret < 0) -+ goto disable_clk_top; -+ -+ platform_set_drvdata(pdev, pc); -+ -+ pc->chip.dev = &pdev->dev; -+ pc->chip.ops = &mtk_pwm_ops; -+ pc->chip.base = -1; -+ pc->chip.npwm = NUM_PWM; -+ -+ ret = pwmchip_add(&pc->chip); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); -+ goto disable_clk_main; -+ } -+ -+ return 0; -+ -+disable_clk_main: -+ clk_unprepare(pc->clk_main); -+disable_clk_top: -+ clk_unprepare(pc->clk_top); -+ -+ return ret; -+} -+ -+static int mtk_pwm_remove(struct platform_device *pdev) -+{ -+ struct mtk_pwm_chip *pc = platform_get_drvdata(pdev); -+ int i; -+ -+ for (i = 0; i < NUM_PWM; i++) -+ pwm_disable(&pc->chip.pwms[i]); -+ -+ return pwmchip_remove(&pc->chip); -+} -+ -+static const struct of_device_id mtk_pwm_of_match[] = { -+ { .compatible = "mediatek,mt7623-pwm" }, -+ { } -+}; -+ -+MODULE_DEVICE_TABLE(of, mtk_pwm_of_match); -+ -+static struct platform_driver mtk_pwm_driver = { -+ .driver = { -+ .name = "mtk-pwm", -+ .owner = THIS_MODULE, -+ .of_match_table = mtk_pwm_of_match, -+ }, -+ .probe = mtk_pwm_probe, -+ .remove = mtk_pwm_remove, -+}; -+ -+module_platform_driver(mtk_pwm_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); -+MODULE_ALIAS("platform:mtk-pwm"); 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 deleted file mode 100644 index 73ac0ee..0000000 --- a/target/linux/mediatek/patches-4.9/0017-mfd-mt6397-Add-MT6323-LED-support-into-MT6397-driver.patch +++ /dev/null @@ -1,27 +0,0 @@ -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/0018-dt-bindings-leds-Add-document-bindings-for-leds-mt63.patch b/target/linux/mediatek/patches-4.9/0018-dt-bindings-leds-Add-document-bindings-for-leds-mt63.patch deleted file mode 100644 index ca0ee04..0000000 --- a/target/linux/mediatek/patches-4.9/0018-dt-bindings-leds-Add-document-bindings-for-leds-mt63.patch +++ /dev/null @@ -1,78 +0,0 @@ -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. - -Signed-off-by: Sean Wang <sean.wang@mediatek.com> ---- - .../devicetree/bindings/leds/leds-mt6323.txt | 60 ++++++++++++++++++++++ - 1 file changed, 60 insertions(+) - create mode 100644 Documentation/devicetree/bindings/leds/leds-mt6323.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/leds/leds-mt6323.txt -@@ -0,0 +1,60 @@ -+Device Tree Bindings for LED support on MT6323 PMIC -+ -+MT6323 LED controller is subfunction provided by MT6323 PMIC, so the LED -+controllers are defined as the subnode of the function node provided by MT6323 -+PMIC controller that is being defined as one kind of Muti-Function Device (MFD) -+using shared bus called PMIC wrapper for each subfunction to access remote -+MT6323 PMIC hardware. -+ -+For MT6323 MFD bindings see: -+Documentation/devicetree/bindings/mfd/mt6397.txt -+For MediaTek PMIC wrapper bindings see: -+Documentation/devicetree/bindings/soc/mediatek/pwrap.txt -+ -+Required properties: -+- compatible : Must be "mediatek,mt6323-led" -+- address-cells : Must be 1 -+- size-cells : Must be 0 -+ -+Each led is represented as a child node of the mediatek,mt6323-led that -+describes the initial behavior for each LED physically and currently only four -+LED child nodes can be supported. -+ -+Required properties for the LED child node: -+- reg : LED channel number (0..3) -+ -+Optional properties for the LED child node: -+- label : See Documentation/devicetree/bindings/leds/common.txt -+- linux,default-trigger : See Documentation/devicetree/bindings/leds/common.txt -+- default-state: See Documentation/devicetree/bindings/leds/common.txt -+ -+Example: -+ -+ mt6323: pmic { -+ compatible = "mediatek,mt6323"; -+ -+ ... -+ -+ mt6323led: leds { -+ compatible = "mediatek,mt6323-led"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ led@0 { -+ reg = <0>; -+ label = "LED0"; -+ linux,default-trigger = "timer"; -+ default-state = "on"; -+ }; -+ led@1 { -+ reg = <1>; -+ label = "LED1"; -+ default-state = "off"; -+ }; -+ led@2 { -+ reg = <2>; -+ label = "LED2"; -+ default-state = "on"; -+ }; -+ }; -+ }; 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 deleted file mode 100644 index c8afdc0..0000000 --- a/target/linux/mediatek/patches-4.9/0019-dt-bindings-mfd-Add-the-description-for-LED-as-the-s.patch +++ /dev/null @@ -1,24 +0,0 @@ -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/0020-leds-Add-LED-support-for-MT6323-PMIC.patch b/target/linux/mediatek/patches-4.9/0020-leds-Add-LED-support-for-MT6323-PMIC.patch deleted file mode 100644 index 37b926d..0000000 --- a/target/linux/mediatek/patches-4.9/0020-leds-Add-LED-support-for-MT6323-PMIC.patch +++ /dev/null @@ -1,539 +0,0 @@ -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 -and/or blinked with the controller. - -Signed-off-by: Sean Wang <sean.wang@mediatek.com> -Reviewed-by: Jacek Anaszewski <jacek.anaszewski@gmail.com> ---- - drivers/leds/Kconfig | 8 + - drivers/leds/leds-mt6323.c | 502 +++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 510 insertions(+) - create mode 100644 drivers/leds/leds-mt6323.c - ---- a/drivers/leds/Kconfig -+++ b/drivers/leds/Kconfig -@@ -117,6 +117,14 @@ config LEDS_MIKROTIK_RB532 - This option enables support for the so called "User LED" of - Mikrotik's Routerboard 532. - -+config LEDS_MT6323 -+ tristate "LED Support for Mediatek MT6323 PMIC" -+ depends on LEDS_CLASS -+ depends on MFD_MT6397 -+ help -+ This option enables support for on-chip LED drivers found on -+ Mediatek MT6323 PMIC. -+ - config LEDS_S3C24XX - tristate "LED Support for Samsung S3C24XX GPIO LEDs" - depends on LEDS_CLASS ---- /dev/null -+++ b/drivers/leds/leds-mt6323.c -@@ -0,0 +1,502 @@ -+/* -+ * LED driver for Mediatek MT6323 PMIC -+ * -+ * 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/kernel.h> -+#include <linux/leds.h> -+#include <linux/mfd/mt6323/registers.h> -+#include <linux/mfd/mt6397/core.h> -+#include <linux/module.h> -+#include <linux/of.h> -+#include <linux/platform_device.h> -+#include <linux/regmap.h> -+ -+/* -+ * Register field for MT6323_TOP_CKPDN0 to enable -+ * 32K clock common for LED device. -+ */ -+#define MT6323_RG_DRV_32K_CK_PDN BIT(11) -+#define MT6323_RG_DRV_32K_CK_PDN_MASK BIT(11) -+ -+/* -+ * Register field for MT6323_TOP_CKPDN2 to enable -+ * individual clock for LED device. -+ */ -+#define MT6323_RG_ISINK_CK_PDN(i) BIT(i) -+#define MT6323_RG_ISINK_CK_PDN_MASK(i) BIT(i) -+ -+/* -+ * Register field for MT6323_TOP_CKCON1 to select -+ * clock source. -+ */ -+#define MT6323_RG_ISINK_CK_SEL_MASK(i) (BIT(10) << (i)) -+ -+/* -+ * Register for MT6323_ISINK_CON0 to setup the -+ * duty cycle of the blink. -+ */ -+#define MT6323_ISINK_CON0(i) (MT6323_ISINK0_CON0 + 0x8 * (i)) -+#define MT6323_ISINK_DIM_DUTY_MASK (0x1f << 8) -+#define MT6323_ISINK_DIM_DUTY(i) (((i) << 8) & \ -+ MT6323_ISINK_DIM_DUTY_MASK) -+ -+/* Register to setup the period of the blink. */ -+#define MT6323_ISINK_CON1(i) (MT6323_ISINK0_CON1 + 0x8 * (i)) -+#define MT6323_ISINK_DIM_FSEL_MASK (0xffff) -+#define MT6323_ISINK_DIM_FSEL(i) ((i) & MT6323_ISINK_DIM_FSEL_MASK) -+ -+/* Register to control the brightness. */ -+#define MT6323_ISINK_CON2(i) (MT6323_ISINK0_CON2 + 0x8 * (i)) -+#define MT6323_ISINK_CH_STEP_SHIFT 12 -+#define MT6323_ISINK_CH_STEP_MASK (0x7 << 12) -+#define MT6323_ISINK_CH_STEP(i) (((i) << 12) & \ -+ MT6323_ISINK_CH_STEP_MASK) -+#define MT6323_ISINK_SFSTR0_TC_MASK (0x3 << 1) -+#define MT6323_ISINK_SFSTR0_TC(i) (((i) << 1) & \ -+ MT6323_ISINK_SFSTR0_TC_MASK) -+#define MT6323_ISINK_SFSTR0_EN_MASK BIT(0) -+#define MT6323_ISINK_SFSTR0_EN BIT(0) -+ -+/* Register to LED channel enablement. */ -+#define MT6323_ISINK_CH_EN_MASK(i) BIT(i) -+#define MT6323_ISINK_CH_EN(i) BIT(i) -+ -+#define MT6323_MAX_PERIOD 10000 -+#define MT6323_MAX_LEDS 4 -+#define MT6323_MAX_BRIGHTNESS 6 -+#define MT6323_UNIT_DUTY 3125 -+#define MT6323_CAL_HW_DUTY(o, p) DIV_ROUND_CLOSEST((o) * 100000ul,\ -+ (p) * MT6323_UNIT_DUTY) -+ -+struct mt6323_leds; -+ -+/** -+ * struct mt6323_led - state container for the LED device -+ * @id: the identifier in MT6323 LED device -+ * @parent: the pointer to MT6323 LED controller -+ * @cdev: LED class device for this LED device -+ * @current_brightness: current state of the LED device -+ */ -+struct mt6323_led { -+ int id; -+ struct mt6323_leds *parent; -+ struct led_classdev cdev; -+ enum led_brightness current_brightness; -+}; -+ -+/** -+ * struct mt6323_leds - state container for holding LED controller -+ * of the driver -+ * @dev: the device pointer -+ * @hw: the underlying hardware providing shared -+ * bus for the register operations -+ * @lock: the lock among process context -+ * @led: the array that contains the state of individual -+ * LED device -+ */ -+struct mt6323_leds { -+ struct device *dev; -+ struct mt6397_chip *hw; -+ /* protect among process context */ -+ struct mutex lock; -+ struct mt6323_led *led[MT6323_MAX_LEDS]; -+}; -+ -+static int mt6323_led_hw_brightness(struct led_classdev *cdev, -+ enum led_brightness brightness) -+{ -+ struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); -+ struct mt6323_leds *leds = led->parent; -+ struct regmap *regmap = leds->hw->regmap; -+ u32 con2_mask = 0, con2_val = 0; -+ int ret; -+ -+ /* -+ * Setup current output for the corresponding -+ * brightness level. -+ */ -+ con2_mask |= MT6323_ISINK_CH_STEP_MASK | -+ MT6323_ISINK_SFSTR0_TC_MASK | -+ MT6323_ISINK_SFSTR0_EN_MASK; -+ con2_val |= MT6323_ISINK_CH_STEP(brightness - 1) | -+ MT6323_ISINK_SFSTR0_TC(2) | -+ MT6323_ISINK_SFSTR0_EN; -+ -+ ret = regmap_update_bits(regmap, MT6323_ISINK_CON2(led->id), -+ con2_mask, con2_val); -+ return ret; -+} -+ -+static int mt6323_led_hw_off(struct led_classdev *cdev) -+{ -+ struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); -+ struct mt6323_leds *leds = led->parent; -+ struct regmap *regmap = leds->hw->regmap; -+ unsigned int status; -+ int ret; -+ -+ status = MT6323_ISINK_CH_EN(led->id); -+ ret = regmap_update_bits(regmap, MT6323_ISINK_EN_CTRL, -+ MT6323_ISINK_CH_EN_MASK(led->id), ~status); -+ if (ret < 0) -+ return ret; -+ -+ usleep_range(100, 300); -+ ret = regmap_update_bits(regmap, MT6323_TOP_CKPDN2, -+ MT6323_RG_ISINK_CK_PDN_MASK(led->id), -+ MT6323_RG_ISINK_CK_PDN(led->id)); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ -+static enum led_brightness -+mt6323_get_led_hw_brightness(struct led_classdev *cdev) -+{ -+ struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); -+ struct mt6323_leds *leds = led->parent; -+ struct regmap *regmap = leds->hw->regmap; -+ unsigned int status; -+ int ret; -+ -+ ret = regmap_read(regmap, MT6323_TOP_CKPDN2, &status); -+ if (ret < 0) -+ return ret; -+ -+ if (status & MT6323_RG_ISINK_CK_PDN_MASK(led->id)) -+ return 0; -+ -+ ret = regmap_read(regmap, MT6323_ISINK_EN_CTRL, &status); -+ if (ret < 0) -+ return ret; -+ -+ if (!(status & MT6323_ISINK_CH_EN(led->id))) -+ return 0; -+ -+ ret = regmap_read(regmap, MT6323_ISINK_CON2(led->id), &status); -+ if (ret < 0) -+ return ret; -+ -+ return ((status & MT6323_ISINK_CH_STEP_MASK) -+ >> MT6323_ISINK_CH_STEP_SHIFT) + 1; -+} -+ -+static int mt6323_led_hw_on(struct led_classdev *cdev, -+ enum led_brightness brightness) -+{ -+ struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); -+ struct mt6323_leds *leds = led->parent; -+ struct regmap *regmap = leds->hw->regmap; -+ unsigned int status; -+ int ret; -+ -+ /* -+ * Setup required clock source, enable the corresponding -+ * clock and channel and let work with continuous blink as -+ * the default. -+ */ -+ ret = regmap_update_bits(regmap, MT6323_TOP_CKCON1, -+ MT6323_RG_ISINK_CK_SEL_MASK(led->id), 0); -+ if (ret < 0) -+ return ret; -+ -+ status = MT6323_RG_ISINK_CK_PDN(led->id); -+ ret = regmap_update_bits(regmap, MT6323_TOP_CKPDN2, -+ MT6323_RG_ISINK_CK_PDN_MASK(led->id), -+ ~status); -+ if (ret < 0) -+ return ret; -+ -+ usleep_range(100, 300); -+ -+ ret = regmap_update_bits(regmap, MT6323_ISINK_EN_CTRL, -+ MT6323_ISINK_CH_EN_MASK(led->id), -+ MT6323_ISINK_CH_EN(led->id)); -+ if (ret < 0) -+ return ret; -+ -+ ret = mt6323_led_hw_brightness(cdev, brightness); -+ if (ret < 0) -+ return ret; -+ -+ ret = regmap_update_bits(regmap, MT6323_ISINK_CON0(led->id), -+ MT6323_ISINK_DIM_DUTY_MASK, -+ MT6323_ISINK_DIM_DUTY(31)); -+ if (ret < 0) -+ return ret; -+ -+ ret = regmap_update_bits(regmap, MT6323_ISINK_CON1(led->id), -+ MT6323_ISINK_DIM_FSEL_MASK, -+ MT6323_ISINK_DIM_FSEL(1000)); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ -+static int mt6323_led_set_blink(struct led_classdev *cdev, -+ unsigned long *delay_on, -+ unsigned long *delay_off) -+{ -+ struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); -+ struct mt6323_leds *leds = led->parent; -+ struct regmap *regmap = leds->hw->regmap; -+ unsigned long period; -+ u8 duty_hw; -+ int ret; -+ -+ /* -+ * Units are in ms, if over the hardware able -+ * to support, fallback into software blink -+ */ -+ period = *delay_on + *delay_off; -+ -+ if (period > MT6323_MAX_PERIOD) -+ return -EINVAL; -+ -+ /* -+ * LED subsystem requires a default user -+ * friendly blink pattern for the LED so using -+ * 1Hz duty cycle 50% here if without specific -+ * value delay_on and delay off being assigned. -+ */ -+ if (!*delay_on && !*delay_off) { -+ *delay_on = 500; -+ *delay_off = 500; -+ } -+ -+ /* -+ * Calculate duty_hw based on the percentage of period during -+ * which the led is ON. -+ */ -+ duty_hw = MT6323_CAL_HW_DUTY(*delay_on, period); -+ -+ /* hardware doesn't support zero duty cycle. */ -+ if (!duty_hw) -+ return -EINVAL; -+ -+ mutex_lock(&leds->lock); -+ /* -+ * Set max_brightness as the software blink behavior -+ * when no blink brightness. -+ */ -+ if (!led->current_brightness) { -+ ret = mt6323_led_hw_on(cdev, cdev->max_brightness); -+ if (ret < 0) -+ goto out; -+ led->current_brightness = cdev->max_brightness; -+ } -+ -+ ret = regmap_update_bits(regmap, MT6323_ISINK_CON0(led->id), -+ MT6323_ISINK_DIM_DUTY_MASK, -+ MT6323_ISINK_DIM_DUTY(duty_hw - 1)); -+ if (ret < 0) -+ goto out; -+ -+ ret = regmap_update_bits(regmap, MT6323_ISINK_CON1(led->id), -+ MT6323_ISINK_DIM_FSEL_MASK, -+ MT6323_ISINK_DIM_FSEL(period - 1)); -+out: -+ mutex_unlock(&leds->lock); -+ -+ return ret; -+} -+ -+static int mt6323_led_set_brightness(struct led_classdev *cdev, -+ enum led_brightness brightness) -+{ -+ struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); -+ struct mt6323_leds *leds = led->parent; -+ int ret; -+ -+ mutex_lock(&leds->lock); -+ -+ if (!led->current_brightness && brightness) { -+ ret = mt6323_led_hw_on(cdev, brightness); -+ if (ret < 0) -+ goto out; -+ } else if (brightness) { -+ ret = mt6323_led_hw_brightness(cdev, brightness); -+ if (ret < 0) -+ goto out; -+ } else { -+ ret = mt6323_led_hw_off(cdev); -+ if (ret < 0) -+ goto out; -+ } -+ -+ led->current_brightness = brightness; -+out: -+ mutex_unlock(&leds->lock); -+ -+ return ret; -+} -+ -+static int mt6323_led_set_dt_default(struct led_classdev *cdev, -+ struct device_node *np) -+{ -+ struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev); -+ const char *state; -+ int ret = 0; -+ -+ led->cdev.name = of_get_property(np, "label", NULL) ? : np->name; -+ led->cdev.default_trigger = of_get_property(np, -+ "linux,default-trigger", -+ NULL); -+ -+ state = of_get_property(np, "default-state", NULL); -+ if (state) { -+ if (!strcmp(state, "keep")) { -+ ret = mt6323_get_led_hw_brightness(cdev); -+ if (ret < 0) -+ return ret; -+ led->current_brightness = ret; -+ ret = 0; -+ } else if (!strcmp(state, "on")) { -+ ret = -+ mt6323_led_set_brightness(cdev, cdev->max_brightness); -+ } else { -+ ret = mt6323_led_set_brightness(cdev, LED_OFF); -+ } -+ } -+ -+ return ret; -+} -+ -+static int mt6323_led_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np = pdev->dev.of_node; -+ struct device_node *child; -+ struct mt6397_chip *hw = dev_get_drvdata(pdev->dev.parent); -+ struct mt6323_leds *leds; -+ struct mt6323_led *led; -+ int ret; -+ unsigned int status; -+ u32 reg; -+ -+ leds = devm_kzalloc(dev, sizeof(*leds), GFP_KERNEL); -+ if (!leds) -+ return -ENOMEM; -+ -+ platform_set_drvdata(pdev, leds); -+ leds->dev = dev; -+ -+ /* -+ * leds->hw points to the underlying bus for the register -+ * controlled. -+ */ -+ leds->hw = hw; -+ mutex_init(&leds->lock); -+ -+ status = MT6323_RG_DRV_32K_CK_PDN; -+ ret = regmap_update_bits(leds->hw->regmap, MT6323_TOP_CKPDN0, -+ MT6323_RG_DRV_32K_CK_PDN_MASK, ~status); -+ if (ret < 0) { -+ dev_err(leds->dev, -+ "Failed to update MT6323_TOP_CKPDN0 Register\n"); -+ return ret; -+ } -+ -+ for_each_available_child_of_node(np, child) { -+ ret = of_property_read_u32(child, "reg", ®); -+ if (ret) { -+ dev_err(dev, "Failed to read led 'reg' property\n"); -+ goto put_child_node; -+ } -+ -+ if (reg < 0 || reg > MT6323_MAX_LEDS || leds->led[reg]) { -+ dev_err(dev, "Invalid led reg %u\n", reg); -+ ret = -EINVAL; -+ goto put_child_node; -+ } -+ -+ led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL); -+ if (!led) { -+ ret = -ENOMEM; -+ goto put_child_node; -+ } -+ -+ leds->led[reg] = led; -+ leds->led[reg]->id = reg; -+ leds->led[reg]->cdev.max_brightness = MT6323_MAX_BRIGHTNESS; -+ leds->led[reg]->cdev.brightness_set_blocking = -+ mt6323_led_set_brightness; -+ leds->led[reg]->cdev.blink_set = mt6323_led_set_blink; -+ leds->led[reg]->cdev.brightness_get = -+ mt6323_get_led_hw_brightness; -+ leds->led[reg]->parent = leds; -+ -+ ret = mt6323_led_set_dt_default(&leds->led[reg]->cdev, child); -+ if (ret < 0) { -+ dev_err(leds->dev, -+ "Failed to LED set default from devicetree\n"); -+ goto put_child_node; -+ } -+ -+ ret = devm_led_classdev_register(dev, &leds->led[reg]->cdev); -+ if (ret) { -+ dev_err(&pdev->dev, "Failed to register LED: %d\n", -+ ret); -+ goto put_child_node; -+ } -+ leds->led[reg]->cdev.dev->of_node = child; -+ } -+ -+ return 0; -+ -+put_child_node: -+ of_node_put(child); -+ return ret; -+} -+ -+static int mt6323_led_remove(struct platform_device *pdev) -+{ -+ struct mt6323_leds *leds = platform_get_drvdata(pdev); -+ int i; -+ -+ /* Turn the LEDs off on driver removal. */ -+ for (i = 0 ; leds->led[i] ; i++) -+ mt6323_led_hw_off(&leds->led[i]->cdev); -+ -+ regmap_update_bits(leds->hw->regmap, MT6323_TOP_CKPDN0, -+ MT6323_RG_DRV_32K_CK_PDN_MASK, -+ MT6323_RG_DRV_32K_CK_PDN); -+ -+ mutex_destroy(&leds->lock); -+ -+ return 0; -+} -+ -+static const struct of_device_id mt6323_led_dt_match[] = { -+ { .compatible = "mediatek,mt6323-led" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mt6323_led_dt_match); -+ -+static struct platform_driver mt6323_led_driver = { -+ .probe = mt6323_led_probe, -+ .remove = mt6323_led_remove, -+ .driver = { -+ .name = "mt6323-led", -+ .of_match_table = mt6323_led_dt_match, -+ }, -+}; -+ -+module_platform_driver(mt6323_led_driver); -+ -+MODULE_DESCRIPTION("LED driver for Mediatek MT6323 PMIC"); -+MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); -+MODULE_LICENSE("GPL"); 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 deleted file mode 100644 index 79e11e8..0000000 --- a/target/linux/mediatek/patches-4.9/0021-mfd-mt6397-Align-the-placement-at-which-the-mfd_cell.patch +++ /dev/null @@ -1,27 +0,0 @@ -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/0022-nand-make-bootrom-work-with-upstream-driver.patch b/target/linux/mediatek/patches-4.9/0022-nand-make-bootrom-work-with-upstream-driver.patch deleted file mode 100644 index f01c841..0000000 --- a/target/linux/mediatek/patches-4.9/0022-nand-make-bootrom-work-with-upstream-driver.patch +++ /dev/null @@ -1,32 +0,0 @@ -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 - if (section >= eccsteps) - return -ERANGE; - -- oob_region->length = fdm->reg_size - fdm->ecc_size; -- oob_region->offset = section * fdm->reg_size + fdm->ecc_size; -+ oob_region->length = fdm->reg_size - 1; -+ oob_region->offset = section * fdm->reg_size + 1; - - return 0; - } -@@ -1114,7 +1114,7 @@ static void mtk_nfc_set_fdm(struct mtk_n - fdm->reg_size = NFI_FDM_MAX_SIZE; - - /* bad block mark storage */ -- fdm->ecc_size = 1; -+ fdm->ecc_size = fdm->reg_size; - } - - static void mtk_nfc_set_bad_mark_ctl(struct mtk_nfc_bad_mark_ctl *bm_ctl, 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 deleted file mode 100644 index 153031b..0000000 --- a/target/linux/mediatek/patches-4.9/0023-rng-add-mediatek-hw-rng.patch +++ /dev/null @@ -1,81 +0,0 @@ -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 deleted file mode 100644 index fbdfbe9..0000000 --- a/target/linux/mediatek/patches-4.9/0024-media-rc-add-driver-for-IR-remote-receiver-on-MT7623.patch +++ /dev/null @@ -1,1034 +0,0 @@ -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/0025-dt-bindings-net-dsa-add-Mediatek-MT7530-binding.patch b/target/linux/mediatek/patches-4.9/0025-dt-bindings-net-dsa-add-Mediatek-MT7530-binding.patch deleted file mode 100644 index 24e13d1..0000000 --- a/target/linux/mediatek/patches-4.9/0025-dt-bindings-net-dsa-add-Mediatek-MT7530-binding.patch +++ /dev/null @@ -1,110 +0,0 @@ -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. - -Cc: devicetree@vger.kernel.org -Signed-off-by: Sean Wang <sean.wang@mediatek.com> -Acked-by: Rob Herring <robh@kernel.org> ---- - .../devicetree/bindings/net/dsa/mt7530.txt | 92 ++++++++++++++++++++++ - 1 file changed, 92 insertions(+) - create mode 100644 Documentation/devicetree/bindings/net/dsa/mt7530.txt - ---- /dev/null -+++ b/Documentation/devicetree/bindings/net/dsa/mt7530.txt -@@ -0,0 +1,92 @@ -+Mediatek MT7530 Ethernet switch -+================================ -+ -+Required properties: -+ -+- compatible: Must be compatible = "mediatek,mt7530"; -+- #address-cells: Must be 1. -+- #size-cells: Must be 0. -+- mediatek,mcm: Boolean; if defined, indicates that either MT7530 is the part -+ on multi-chip module belong to MT7623A has or the remotely standalone -+ chip as the function MT7623N reference board provided for. -+- core-supply: Phandle to the regulator node necessary for the core power. -+- io-supply: Phandle to the regulator node necessary for the I/O power. -+ See Documentation/devicetree/bindings/regulator/mt6323-regulator.txt -+ for details for the regulator setup on these boards. -+ -+If the property mediatek,mcm isn't defined, following property is required -+ -+- reset-gpios: Should be a gpio specifier for a reset line. -+ -+Else, following properties are required -+ -+- resets : Phandle pointing to the system reset controller with -+ line index for the ethsys. -+- reset-names : Should be set to "mcm". -+ -+Required properties for the child nodes within ports container: -+ -+- reg: Port address described must be 6 for CPU port and from 0 to 5 for -+ user ports. -+- phy-mode: String, must be either "trgmii" or "rgmii" for port labeled -+ "cpu". -+ -+See Documentation/devicetree/bindings/dsa/dsa.txt for a list of additional -+required, optional properties and how the integrated switch subnodes must -+be specified. -+ -+Example: -+ -+ &mdio0 { -+ switch@0 { -+ compatible = "mediatek,mt7530"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0>; -+ -+ core-supply = <&mt6323_vpa_reg>; -+ io-supply = <&mt6323_vemc3v3_reg>; -+ reset-gpios = <&pio 33 0>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0>; -+ port@0 { -+ reg = <0>; -+ label = "lan0"; -+ }; -+ -+ port@1 { -+ reg = <1>; -+ label = "lan1"; -+ }; -+ -+ port@2 { -+ reg = <2>; -+ label = "lan2"; -+ }; -+ -+ port@3 { -+ reg = <3>; -+ label = "lan3"; -+ }; -+ -+ port@4 { -+ reg = <4>; -+ label = "wan"; -+ }; -+ -+ port@6 { -+ reg = <6>; -+ label = "cpu"; -+ ethernet = <&gmac0>; -+ phy-mode = "trgmii"; -+ fixed-link { -+ speed = <1000>; -+ full-duplex; -+ }; -+ }; -+ }; -+ }; -+ }; 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 deleted file mode 100644 index 8a6d593..0000000 --- a/target/linux/mediatek/patches-4.9/0026-net-mediatek-backport-v4.10-driver.patch +++ /dev/null @@ -1,1788 +0,0 @@ -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/0027-net-next-mediatek-fix-DQL-support.patch b/target/linux/mediatek/patches-4.9/0027-net-next-mediatek-fix-DQL-support.patch deleted file mode 100644 index d21c8ee..0000000 --- a/target/linux/mediatek/patches-4.9/0027-net-next-mediatek-fix-DQL-support.patch +++ /dev/null @@ -1,93 +0,0 @@ -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 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 -results in the amount of data, that DQL says is in the queue incorrect. As -the data from multiple devices is infact enqueued. This makes any decision -based on these value non deterministic. Fix this by tracking all TX -traffic, regardless of the MAC it belongs to in the DQL of all devices -using the DMA. - -Signed-off-by: John Crispin <john@phrozen.org> ---- - 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 -@@ -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))); - -- netdev_sent_queue(dev, skb->len); -+ /* 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); -+ } -+ - skb_tx_timestamp(skb); - - ring->next_free = mtk_qdma_phys_to_virt(ring, txd->txd2); -@@ -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; -- unsigned int done[MTK_MAX_DEVS]; -- unsigned int bytes[MTK_MAX_DEVS]; -+ int total = 0, done = 0; -+ unsigned int bytes = 0; - u32 cpu, dma; - static int condition; -- int total = 0, i; -- -- memset(done, 0, sizeof(done)); -- memset(bytes, 0, sizeof(bytes)); -+ int i; - - 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) && budget) { -+ while ((cpu != dma) && done < budget) { - u32 next_cpu = desc->txd2; - int mac = 0; - -@@ -1035,9 +1041,8 @@ static int mtk_poll_tx(struct mtk_eth *e - } - - if (skb != (struct sk_buff *)MTK_DMA_DUMMY_DESC) { -- bytes[mac] += skb->len; -- done[mac]++; -- budget--; -+ bytes += skb->len; -+ done++; - } - mtk_tx_unmap(eth, tx_buf); - -@@ -1049,11 +1054,13 @@ 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] || !done[i]) -+ if (!eth->netdev[i]) - continue; -- netdev_completed_queue(eth->netdev[i], done[i], bytes[i]); -- total += done[i]; -+ netdev_completed_queue(eth->netdev[i], done, bytes); - } - - if (mtk_queue_stopped(eth) && diff --git a/target/linux/mediatek/patches-4.9/0028-net-next-dsa-add-Mediatek-tag-RX-TX-handler.patch b/target/linux/mediatek/patches-4.9/0028-net-next-dsa-add-Mediatek-tag-RX-TX-handler.patch deleted file mode 100644 index ef545e3..0000000 --- a/target/linux/mediatek/patches-4.9/0028-net-next-dsa-add-Mediatek-tag-RX-TX-handler.patch +++ /dev/null @@ -1,192 +0,0 @@ -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. -The tag is being added after the source MAC address in the ethernet -header. - -Signed-off-by: Sean Wang <sean.wang@mediatek.com> -Signed-off-by: Landen Chao <Landen.Chao@mediatek.com> -Reviewed-by: Andrew Lunn <andrew@lunn.ch> -Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> ---- - include/net/dsa.h | 1 + - net/dsa/Kconfig | 2 + - net/dsa/Makefile | 1 + - net/dsa/dsa.c | 3 ++ - net/dsa/dsa_priv.h | 3 ++ - net/dsa/tag_mtk.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - 6 files changed, 127 insertions(+) - create mode 100644 net/dsa/tag_mtk.c - ---- a/include/net/dsa.h -+++ b/include/net/dsa.h -@@ -27,6 +27,7 @@ enum dsa_tag_protocol { - DSA_TAG_PROTO_EDSA, - DSA_TAG_PROTO_BRCM, - DSA_TAG_PROTO_QCA, -+ DSA_TAG_PROTO_MTK, - DSA_TAG_LAST, /* MUST BE LAST */ - }; - ---- a/net/dsa/Kconfig -+++ b/net/dsa/Kconfig -@@ -42,4 +42,6 @@ config NET_DSA_TAG_TRAILER - config NET_DSA_TAG_QCA - bool - -+config NET_DSA_TAG_MTK -+ bool - endif ---- a/net/dsa/Makefile -+++ b/net/dsa/Makefile -@@ -8,3 +8,4 @@ dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += ta - dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o - dsa_core-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o - dsa_core-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o -+dsa_core-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o ---- a/net/dsa/dsa.c -+++ b/net/dsa/dsa.c -@@ -57,6 +57,9 @@ const struct dsa_device_ops *dsa_device_ - #ifdef CONFIG_NET_DSA_TAG_QCA - [DSA_TAG_PROTO_QCA] = &qca_netdev_ops, - #endif -+#ifdef CONFIG_NET_DSA_TAG_MTK -+ [DSA_TAG_PROTO_MTK] = &mtk_netdev_ops, -+#endif - [DSA_TAG_PROTO_NONE] = &none_ops, - }; - ---- a/net/dsa/dsa_priv.h -+++ b/net/dsa/dsa_priv.h -@@ -84,4 +84,7 @@ extern const struct dsa_device_ops brcm_ - /* tag_qca.c */ - extern const struct dsa_device_ops qca_netdev_ops; - -+/* tag_mtk.c */ -+extern const struct dsa_device_ops mtk_netdev_ops; -+ - #endif ---- /dev/null -+++ b/net/dsa/tag_mtk.c -@@ -0,0 +1,117 @@ -+/* -+ * Mediatek DSA Tag support -+ * Copyright (C) 2017 Landen Chao <landen.chao@mediatek.com> -+ * 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 version 2 and -+ * only version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+ -+#include <linux/etherdevice.h> -+#include "dsa_priv.h" -+ -+#define MTK_HDR_LEN 4 -+#define MTK_HDR_RECV_SOURCE_PORT_MASK GENMASK(2, 0) -+#define MTK_HDR_XMIT_DP_BIT_MASK GENMASK(5, 0) -+ -+static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, -+ struct net_device *dev) -+{ -+ struct dsa_slave_priv *p = netdev_priv(dev); -+ u8 *mtk_tag; -+ -+ if (skb_cow_head(skb, MTK_HDR_LEN) < 0) -+ goto out_free; -+ -+ skb_push(skb, MTK_HDR_LEN); -+ -+ memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN); -+ -+ /* Build the tag after the MAC Source Address */ -+ mtk_tag = skb->data + 2 * ETH_ALEN; -+ mtk_tag[0] = 0; -+ mtk_tag[1] = (1 << p->dp->index) & MTK_HDR_XMIT_DP_BIT_MASK; -+ mtk_tag[2] = 0; -+ mtk_tag[3] = 0; -+ -+ return skb; -+ -+out_free: -+ kfree_skb(skb); -+ return NULL; -+} -+ -+static int mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev, -+ struct packet_type *pt, struct net_device *orig_dev) -+{ -+ struct dsa_switch_tree *dst = dev->dsa_ptr; -+ struct dsa_switch *ds; -+ int port; -+ __be16 *phdr, hdr; -+ -+ if (unlikely(!dst)) -+ goto out_drop; -+ -+ skb = skb_unshare(skb, GFP_ATOMIC); -+ if (!skb) -+ goto out; -+ -+ if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN))) -+ goto out_drop; -+ -+ /* The MTK header is added by the switch between src addr -+ * and ethertype at this point, skb->data points to 2 bytes -+ * after src addr so header should be 2 bytes right before. -+ */ -+ phdr = (__be16 *)(skb->data - 2); -+ hdr = ntohs(*phdr); -+ -+ /* Remove MTK tag and recalculate checksum. */ -+ skb_pull_rcsum(skb, MTK_HDR_LEN); -+ -+ memmove(skb->data - ETH_HLEN, -+ skb->data - ETH_HLEN - MTK_HDR_LEN, -+ 2 * ETH_ALEN); -+ -+ /* This protocol doesn't support cascading multiple -+ * switches so it's safe to assume the switch is first -+ * in the tree. -+ */ -+ ds = dst->ds[0]; -+ if (!ds) -+ goto out_drop; -+ -+ /* Get source port information */ -+ port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK); -+ if (!ds->ports[port].netdev) -+ goto out_drop; -+ -+ /* Update skb & forward the frame accordingly */ -+ skb_push(skb, ETH_HLEN); -+ -+ skb->pkt_type = PACKET_HOST; -+ skb->dev = ds->ports[port].netdev; -+ skb->protocol = eth_type_trans(skb, skb->dev); -+ -+ skb->dev->stats.rx_packets++; -+ skb->dev->stats.rx_bytes += skb->len; -+ -+ netif_receive_skb(skb); -+ -+ return 0; -+ -+out_drop: -+ kfree_skb(skb); -+out: -+ return 0; -+} -+ -+const struct dsa_device_ops mtk_netdev_ops = { -+ .xmit = mtk_tag_xmit, -+ .rcv = mtk_tag_rcv, -+}; diff --git a/target/linux/mediatek/patches-4.9/0029-net-next-ethernet-mediatek-add-CDM-able-to-recognize.patch b/target/linux/mediatek/patches-4.9/0029-net-next-ethernet-mediatek-add-CDM-able-to-recognize.patch deleted file mode 100644 index 5c7e6e4..0000000 --- a/target/linux/mediatek/patches-4.9/0029-net-next-ethernet-mediatek-add-CDM-able-to-recognize.patch +++ /dev/null @@ -1,48 +0,0 @@ -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 -handled incorrectly by CDM. The setup is also working out for general -untag packets as well. - -Signed-off-by: Sean Wang <sean.wang@mediatek.com> -Signed-off-by: Landen Chao <Landen.Chao@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 | 6 ++++++ - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++++ - 2 files changed, 10 insertions(+) - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -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. -+ */ -+ 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); - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -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 -+#define MTK_CDMQ_STAG_EN BIT(0) -+ - /* CDMP Exgress Control Register */ - #define MTK_CDMP_EG_CTRL 0x404 - diff --git a/target/linux/mediatek/patches-4.9/0030-net-next-dsa-add-dsa-support-for-Mediatek-MT7530-swi.patch b/target/linux/mediatek/patches-4.9/0030-net-next-dsa-add-dsa-support-for-Mediatek-MT7530-swi.patch deleted file mode 100644 index 47a0683..0000000 --- a/target/linux/mediatek/patches-4.9/0030-net-next-dsa-add-dsa-support-for-Mediatek-MT7530-swi.patch +++ /dev/null @@ -1,1584 +0,0 @@ -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 -includes 7-port Gigabit Ethernet MAC and 5-port Gigabit Ethernet PHY. -Among these ports, The port from 0 to 4 are the user ports connecting -with the remote devices while the port 5 and 6 are the CPU ports -connecting into Mediatek Ethernet GMAC. - -For port 6, it can communicate with the CPU via Mediatek Ethernet GMAC -through either the TRGMII or RGMII which could be controlled by phy-mode -in the dt-bindings to specify which mode is preferred to use. And for -port 5, only RGMII can be specified. However, currently, only port 6 is -being supported in this DSA driver. - -The driver is made with the reference to qca8k and other existing DSA -driver. The most of the essential callbacks of the DSA are already -support in the driver, including tag insert for user port distinguishing, -port control, bridge offloading, STP setup and ethtool operation to allow -DSA to model each user port into a standalone netdevice as the other DSA -driver had done. - -Signed-off-by: Sean Wang <sean.wang@mediatek.com> -Signed-off-by: Landen Chao <Landen.Chao@mediatek.com> ---- - drivers/net/dsa/Kconfig | 8 + - drivers/net/dsa/Makefile | 2 +- - drivers/net/dsa/mt7530.c | 1126 ++++++++++++++++++++++++++++++++++++++++++++++ - drivers/net/dsa/mt7530.h | 390 ++++++++++++++++ - 4 files changed, 1525 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/dsa/mt7530.c - create mode 100644 drivers/net/dsa/mt7530.h - ---- a/drivers/net/dsa/Kconfig -+++ b/drivers/net/dsa/Kconfig -@@ -34,4 +34,12 @@ config NET_DSA_QCA8K - This enables support for the Qualcomm Atheros QCA8K Ethernet - switch chips. - -+config NET_DSA_MT7530 -+ tristate "Mediatek MT7530 Ethernet switch support" -+ depends on NET_DSA -+ select NET_DSA_TAG_MTK -+ ---help--- -+ This enables support for the Mediatek MT7530 Ethernet switch -+ chip. -+ - endmenu ---- a/drivers/net/dsa/Makefile -+++ b/drivers/net/dsa/Makefile -@@ -1,6 +1,6 @@ - obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o - obj-$(CONFIG_NET_DSA_BCM_SF2) += bcm_sf2.o - obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o -- -+obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o - obj-y += b53/ - obj-y += mv88e6xxx/ ---- /dev/null -+++ b/drivers/net/dsa/mt7530.c -@@ -0,0 +1,1126 @@ -+/* -+ * Mediatek MT7530 DSA Switch driver -+ * 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 version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ */ -+#include <linux/etherdevice.h> -+#include <linux/if_bridge.h> -+#include <linux/iopoll.h> -+#include <linux/mdio.h> -+#include <linux/mfd/syscon.h> -+#include <linux/module.h> -+#include <linux/netdevice.h> -+#include <linux/of_gpio.h> -+#include <linux/of_mdio.h> -+#include <linux/of_net.h> -+#include <linux/of_platform.h> -+#include <linux/phy.h> -+#include <linux/regmap.h> -+#include <linux/regulator/consumer.h> -+#include <linux/reset.h> -+#include <net/dsa.h> -+#include <net/switchdev.h> -+ -+#include "mt7530.h" -+ -+/* String, offset, and register size in bytes if different from 4 bytes */ -+static const struct mt7530_mib_desc mt7530_mib[] = { -+ MIB_DESC(1, 0x00, "TxDrop"), -+ MIB_DESC(1, 0x04, "TxCrcErr"), -+ MIB_DESC(1, 0x08, "TxUnicast"), -+ MIB_DESC(1, 0x0c, "TxMulticast"), -+ MIB_DESC(1, 0x10, "TxBroadcast"), -+ MIB_DESC(1, 0x14, "TxCollision"), -+ MIB_DESC(1, 0x18, "TxSingleCollision"), -+ MIB_DESC(1, 0x1c, "TxMultipleCollision"), -+ MIB_DESC(1, 0x20, "TxDeferred"), -+ MIB_DESC(1, 0x24, "TxLateCollision"), -+ MIB_DESC(1, 0x28, "TxExcessiveCollistion"), -+ MIB_DESC(1, 0x2c, "TxPause"), -+ MIB_DESC(1, 0x30, "TxPktSz64"), -+ MIB_DESC(1, 0x34, "TxPktSz65To127"), -+ MIB_DESC(1, 0x38, "TxPktSz128To255"), -+ MIB_DESC(1, 0x3c, "TxPktSz256To511"), -+ MIB_DESC(1, 0x40, "TxPktSz512To1023"), -+ MIB_DESC(1, 0x44, "Tx1024ToMax"), -+ MIB_DESC(2, 0x48, "TxBytes"), -+ MIB_DESC(1, 0x60, "RxDrop"), -+ MIB_DESC(1, 0x64, "RxFiltering"), -+ MIB_DESC(1, 0x6c, "RxMulticast"), -+ MIB_DESC(1, 0x70, "RxBroadcast"), -+ MIB_DESC(1, 0x74, "RxAlignErr"), -+ MIB_DESC(1, 0x78, "RxCrcErr"), -+ MIB_DESC(1, 0x7c, "RxUnderSizeErr"), -+ MIB_DESC(1, 0x80, "RxFragErr"), -+ MIB_DESC(1, 0x84, "RxOverSzErr"), -+ MIB_DESC(1, 0x88, "RxJabberErr"), -+ MIB_DESC(1, 0x8c, "RxPause"), -+ MIB_DESC(1, 0x90, "RxPktSz64"), -+ MIB_DESC(1, 0x94, "RxPktSz65To127"), -+ MIB_DESC(1, 0x98, "RxPktSz128To255"), -+ MIB_DESC(1, 0x9c, "RxPktSz256To511"), -+ MIB_DESC(1, 0xa0, "RxPktSz512To1023"), -+ MIB_DESC(1, 0xa4, "RxPktSz1024ToMax"), -+ MIB_DESC(2, 0xa8, "RxBytes"), -+ MIB_DESC(1, 0xb0, "RxCtrlDrop"), -+ MIB_DESC(1, 0xb4, "RxIngressDrop"), -+ MIB_DESC(1, 0xb8, "RxArlDrop"), -+}; -+ -+static struct mt7530_priv *lpriv; -+static void mt7530_port_disable(struct dsa_switch *ds, int port, -+ struct phy_device *phy); -+static int mt7530_cpu_port_enable(struct mt7530_priv *priv, -+ int port); -+ -+static int -+mt7623_trgmii_write(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ int ret; -+ -+ ret = regmap_write(priv->ethernet, TRGMII_BASE(reg), val); -+ if (ret < 0) -+ dev_err(priv->dev, -+ "failed to priv write register\n"); -+ return ret; -+} -+ -+static u32 -+mt7623_trgmii_read(struct mt7530_priv *priv, u32 reg) -+{ -+ int ret; -+ u32 val; -+ -+ ret = regmap_read(priv->ethernet, TRGMII_BASE(reg), &val); -+ if (ret < 0) { -+ dev_err(priv->dev, -+ "failed to priv read register\n"); -+ return ret; -+ } -+ -+ return val; -+} -+ -+static void -+mt7623_trgmii_rmw(struct mt7530_priv *priv, u32 reg, -+ u32 mask, u32 set) -+{ -+ u32 val; -+ -+ val = mt7623_trgmii_read(priv, reg); -+ val &= ~mask; -+ val |= set; -+ mt7623_trgmii_write(priv, reg, val); -+} -+ -+static void -+mt7623_trgmii_set(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ mt7623_trgmii_rmw(priv, reg, 0, val); -+} -+ -+static void -+mt7623_trgmii_clear(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ mt7623_trgmii_rmw(priv, reg, val, 0); -+} -+ -+static int -+core_read_mmd_indirect(struct mt7530_priv *priv, int prtad, int devad) -+{ -+ struct mii_bus *bus = priv->bus; -+ int value, ret; -+ -+ /* Write the desired MMD Devad */ -+ ret = bus->write(bus, 0, MII_MMD_CTRL, devad); -+ if (ret < 0) -+ goto err; -+ -+ /* Write the desired MMD register address */ -+ ret = bus->write(bus, 0, MII_MMD_DATA, prtad); -+ if (ret < 0) -+ goto err; -+ -+ /* Select the Function : DATA with no post increment */ -+ ret = bus->write(bus, 0, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR)); -+ if (ret < 0) -+ goto err; -+ -+ /* Read the content of the MMD's selected register */ -+ value = bus->read(bus, 0, MII_MMD_DATA); -+ -+ return value; -+err: -+ dev_err(&bus->dev, "failed to read mmd register\n"); -+ -+ return ret; -+} -+ -+static int -+core_write_mmd_indirect(struct mt7530_priv *priv, int prtad, -+ int devad, u32 data) -+{ -+ struct mii_bus *bus = priv->bus; -+ int ret; -+ -+ /* Write the desired MMD Devad */ -+ ret = bus->write(bus, 0, MII_MMD_CTRL, devad); -+ if (ret < 0) -+ goto err; -+ -+ /* Write the desired MMD register address */ -+ ret = bus->write(bus, 0, MII_MMD_DATA, prtad); -+ if (ret < 0) -+ goto err; -+ -+ /* Select the Function : DATA with no post increment */ -+ ret = bus->write(bus, 0, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR)); -+ if (ret < 0) -+ goto err; -+ -+ /* Write the data into MMD's selected register */ -+ ret = bus->write(bus, 0, MII_MMD_DATA, data); -+err: -+ if (ret < 0) -+ dev_err(&bus->dev, -+ "failed to write mmd register\n"); -+ return ret; -+} -+ -+static void -+core_write(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ struct mii_bus *bus = priv->bus; -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val); -+ -+ mutex_unlock(&bus->mdio_lock); -+} -+ -+static void -+core_rmw(struct mt7530_priv *priv, u32 reg, u32 mask, u32 set) -+{ -+ struct mii_bus *bus = priv->bus; -+ u32 val; -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ val = core_read_mmd_indirect(priv, reg, MDIO_MMD_VEND2); -+ val &= ~mask; -+ val |= set; -+ core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val); -+ -+ mutex_unlock(&bus->mdio_lock); -+} -+ -+static void -+core_set(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ core_rmw(priv, reg, 0, val); -+} -+ -+static void -+core_clear(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ core_rmw(priv, reg, val, 0); -+} -+ -+static int -+mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ struct mii_bus *bus = priv->bus; -+ u16 page, r, lo, hi; -+ int ret; -+ -+ page = (reg >> 6) & 0x3ff; -+ r = (reg >> 2) & 0xf; -+ lo = val & 0xffff; -+ hi = val >> 16; -+ -+ /* MT7530 uses 31 as the pseudo port */ -+ ret = bus->write(bus, 0x1f, 0x1f, page); -+ if (ret < 0) -+ goto err; -+ -+ ret = bus->write(bus, 0x1f, r, lo); -+ if (ret < 0) -+ goto err; -+ -+ ret = bus->write(bus, 0x1f, 0x10, hi); -+err: -+ if (ret < 0) -+ dev_err(&bus->dev, -+ "failed to write mt7530 register\n"); -+ return ret; -+} -+ -+static u32 -+mt7530_mii_read(struct mt7530_priv *priv, u32 reg) -+{ -+ struct mii_bus *bus = priv->bus; -+ u16 page, r, lo, hi; -+ int ret; -+ -+ page = (reg >> 6) & 0x3ff; -+ r = (reg >> 2) & 0xf; -+ -+ /* MT7530 uses 31 as the pseudo port */ -+ ret = bus->write(bus, 0x1f, 0x1f, page); -+ if (ret < 0) { -+ dev_err(&bus->dev, -+ "failed to read mt7530 register\n"); -+ return ret; -+ } -+ -+ lo = bus->read(bus, 0x1f, r); -+ hi = bus->read(bus, 0x1f, 0x10); -+ -+ return (hi << 16) | (lo & 0xffff); -+} -+ -+static void -+mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ struct mii_bus *bus = priv->bus; -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ mt7530_mii_write(priv, reg, val); -+ -+ mutex_unlock(&bus->mdio_lock); -+} -+ -+static u32 -+_mt7530_read(u32 reg) -+{ -+ struct mt7530_priv *priv = lpriv; -+ struct mii_bus *bus = priv->bus; -+ u32 val; -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ val = mt7530_mii_read(priv, reg); -+ -+ mutex_unlock(&bus->mdio_lock); -+ -+ return val; -+} -+ -+static u32 -+mt7530_read(struct mt7530_priv *priv, u32 reg) -+{ -+ return _mt7530_read(reg); -+} -+ -+static void -+mt7530_rmw(struct mt7530_priv *priv, u32 reg, -+ u32 mask, u32 set) -+{ -+ struct mii_bus *bus = priv->bus; -+ u32 val; -+ -+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); -+ -+ val = mt7530_mii_read(priv, reg); -+ val &= ~mask; -+ val |= set; -+ mt7530_mii_write(priv, reg, val); -+ -+ mutex_unlock(&bus->mdio_lock); -+} -+ -+static void -+mt7530_set(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ mt7530_rmw(priv, reg, 0, val); -+} -+ -+static void -+mt7530_clear(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ mt7530_rmw(priv, reg, val, 0); -+} -+ -+static int -+mt7530_fdb_cmd(struct mt7530_priv *priv, enum mt7530_fdb_cmd cmd, u32 *rsp) -+{ -+ u32 val; -+ int ret; -+ -+ /* Set the command operating upon the MAC address entries */ -+ val = ATC_BUSY | ATC_MAT(0) | cmd; -+ mt7530_write(priv, MT7530_ATC, val); -+ -+ ret = readx_poll_timeout(_mt7530_read, MT7530_ATC, val, -+ !(val & ATC_BUSY), 20, 20000); -+ if (ret < 0) { -+ dev_err(priv->dev, "reset timeout\n"); -+ return ret; -+ } -+ -+ /* Additional sanity for read command if the specified -+ * entry is invalid -+ */ -+ val = mt7530_read(priv, MT7530_ATC); -+ if ((cmd == MT7530_FDB_READ) && (val & ATC_INVALID)) -+ return -EINVAL; -+ -+ if (rsp) -+ *rsp = val; -+ -+ return 0; -+} -+ -+static void -+mt7530_fdb_read(struct mt7530_priv *priv, struct mt7530_fdb *fdb) -+{ -+ u32 reg[3]; -+ int i; -+ -+ /* Read from ARL table into an array */ -+ for (i = 0; i < 3; i++) { -+ reg[i] = mt7530_read(priv, MT7530_TSRA1 + (i * 4)); -+ -+ dev_dbg(priv->dev, "%s(%d) reg[%d]=0x%x\n", -+ __func__, __LINE__, i, reg[i]); -+ } -+ -+ fdb->vid = (reg[1] >> CVID) & CVID_MASK; -+ fdb->aging = (reg[2] >> AGE_TIMER) & AGE_TIMER_MASK; -+ fdb->port_mask = (reg[2] >> PORT_MAP) & PORT_MAP_MASK; -+ fdb->mac[0] = (reg[0] >> MAC_BYTE_0) & MAC_BYTE_MASK; -+ fdb->mac[1] = (reg[0] >> MAC_BYTE_1) & MAC_BYTE_MASK; -+ fdb->mac[2] = (reg[0] >> MAC_BYTE_2) & MAC_BYTE_MASK; -+ fdb->mac[3] = (reg[0] >> MAC_BYTE_3) & MAC_BYTE_MASK; -+ fdb->mac[4] = (reg[1] >> MAC_BYTE_4) & MAC_BYTE_MASK; -+ fdb->mac[5] = (reg[1] >> MAC_BYTE_5) & MAC_BYTE_MASK; -+ fdb->noarp = ((reg[2] >> ENT_STATUS) & ENT_STATUS_MASK) == STATIC_ENT; -+} -+ -+static void -+mt7530_fdb_write(struct mt7530_priv *priv, u16 vid, -+ u8 port_mask, const u8 *mac, -+ u8 aging, u8 type) -+{ -+ u32 reg[3] = { 0 }; -+ int i; -+ -+ reg[1] |= vid & CVID_MASK; -+ reg[2] |= (aging & AGE_TIMER_MASK) << AGE_TIMER; -+ reg[2] |= (port_mask & PORT_MAP_MASK) << PORT_MAP; -+ /* STATIC_ENT indicate that entry is static wouldn't -+ * be aged out and STATIC_EMP specified as erasing an -+ * entry -+ */ -+ reg[2] |= (type & ENT_STATUS_MASK) << ENT_STATUS; -+ reg[1] |= mac[5] << MAC_BYTE_5; -+ reg[1] |= mac[4] << MAC_BYTE_4; -+ reg[0] |= mac[3] << MAC_BYTE_3; -+ reg[0] |= mac[2] << MAC_BYTE_2; -+ reg[0] |= mac[1] << MAC_BYTE_1; -+ reg[0] |= mac[0] << MAC_BYTE_0; -+ -+ /* Write array into the ARL table */ -+ for (i = 0; i < 3; i++) -+ mt7530_write(priv, MT7530_ATA1 + (i * 4), reg[i]); -+} -+ -+static int -+mt7530_pad_clk_setup(struct dsa_switch *ds, int mode) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ u32 ncpo1, ssc_delta, trgint, i; -+ -+ switch (mode) { -+ case PHY_INTERFACE_MODE_RGMII: -+ trgint = 0; -+ ncpo1 = 0x0c80; -+ ssc_delta = 0x87; -+ break; -+ case PHY_INTERFACE_MODE_TRGMII: -+ trgint = 1; -+ ncpo1 = 0x1400; -+ ssc_delta = 0x57; -+ break; -+ default: -+ dev_err(priv->dev, "xMII mode %d not supported\n", mode); -+ return -EINVAL; -+ } -+ -+ mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK, -+ P6_INTF_MODE(trgint)); -+ -+ /* Lower Tx Driving for TRGMII path */ -+ for (i = 0 ; i < NUM_TRGMII_CTRL ; i++) -+ mt7530_write(priv, MT7530_TRGMII_TD_ODT(i), -+ TD_DM_DRVP(8) | TD_DM_DRVN(8)); -+ -+ /* Setup core clock for MT7530 */ -+ if (!trgint) { -+ /* Disable MT7530 core clock */ -+ core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); -+ -+ /* Disable PLL, since phy_device has not yet been created -+ * provided for phy_[read,write]_mmd_indirect is called, we -+ * provide our own core_write_mmd_indirect to complete this -+ * function. -+ */ -+ core_write_mmd_indirect(priv, -+ CORE_GSWPLL_GRP1, -+ MDIO_MMD_VEND2, -+ 0); -+ -+ /* Set core clock into 500Mhz */ -+ core_write(priv, CORE_GSWPLL_GRP2, -+ RG_GSWPLL_POSDIV_500M(1) | -+ RG_GSWPLL_FBKDIV_500M(25)); -+ -+ /* Enable PLL */ -+ core_write(priv, CORE_GSWPLL_GRP1, -+ RG_GSWPLL_EN_PRE | -+ RG_GSWPLL_POSDIV_200M(2) | -+ RG_GSWPLL_FBKDIV_200M(32)); -+ -+ /* Enable MT7530 core clock */ -+ core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); -+ } -+ -+ /* Setup the MT7530 TRGMII Tx Clock */ -+ core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); -+ core_write(priv, CORE_PLL_GROUP5, RG_LCDDS_PCW_NCPO1(ncpo1)); -+ core_write(priv, CORE_PLL_GROUP6, RG_LCDDS_PCW_NCPO0(0)); -+ core_write(priv, CORE_PLL_GROUP10, RG_LCDDS_SSC_DELTA(ssc_delta)); -+ core_write(priv, CORE_PLL_GROUP11, RG_LCDDS_SSC_DELTA1(ssc_delta)); -+ core_write(priv, CORE_PLL_GROUP4, -+ RG_SYSPLL_DDSFBK_EN | RG_SYSPLL_BIAS_EN | -+ RG_SYSPLL_BIAS_LPF_EN); -+ core_write(priv, CORE_PLL_GROUP2, -+ RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN | -+ RG_SYSPLL_POSDIV(1)); -+ core_write(priv, CORE_PLL_GROUP7, -+ RG_LCDDS_PCW_NCPO_CHG | RG_LCCDS_C(3) | -+ RG_LCDDS_PWDB | RG_LCDDS_ISO_EN); -+ core_set(priv, CORE_TRGMII_GSW_CLK_CG, -+ REG_GSWCK_EN | REG_TRGMIICK_EN); -+ -+ if (!trgint) -+ for (i = 0 ; i < NUM_TRGMII_CTRL; i++) -+ mt7530_rmw(priv, MT7530_TRGMII_RD(i), -+ RD_TAP_MASK, RD_TAP(16)); -+ else -+ mt7623_trgmii_set(priv, GSW_INTF_MODE, INTF_MODE_TRGMII); -+ -+ return 0; -+} -+ -+static int -+mt7623_pad_clk_setup(struct dsa_switch *ds) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ int i; -+ -+ for (i = 0 ; i < NUM_TRGMII_CTRL; i++) -+ mt7623_trgmii_write(priv, GSW_TRGMII_TD_ODT(i), -+ TD_DM_DRVP(8) | TD_DM_DRVN(8)); -+ -+ mt7623_trgmii_set(priv, GSW_TRGMII_RCK_CTRL, RX_RST | RXC_DQSISEL); -+ mt7623_trgmii_clear(priv, GSW_TRGMII_RCK_CTRL, RX_RST); -+ -+ return 0; -+} -+ -+static void -+mt7530_mib_reset(struct dsa_switch *ds) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ mt7530_write(priv, MT7530_MIB_CCR, CCR_MIB_FLUSH); -+ mt7530_write(priv, MT7530_MIB_CCR, CCR_MIB_ACTIVATE); -+} -+ -+static void -+mt7530_port_set_status(struct mt7530_priv *priv, int port, int enable) -+{ -+ u32 mask = PMCR_TX_EN | PMCR_RX_EN; -+ -+ if (enable) -+ mt7530_set(priv, MT7530_PMCR_P(port), mask); -+ else -+ mt7530_clear(priv, MT7530_PMCR_P(port), mask); -+} -+ -+static int -+mt7530_setup(struct dsa_switch *ds) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ int ret, i; -+ u32 id, val; -+ struct device_node *dn; -+ -+ /* The parent node of master_netdev which holds the common system -+ * controller also is the container for two GMACs nodes representing -+ * as two netdev instances. -+ */ -+ dn = ds->master_netdev->dev.of_node->parent; -+ priv->ethernet = syscon_node_to_regmap(dn); -+ if (IS_ERR(priv->ethernet)) -+ return PTR_ERR(priv->ethernet); -+ -+ regulator_set_voltage(priv->core_pwr, 1000000, 1000000); -+ ret = regulator_enable(priv->core_pwr); -+ if (ret < 0) { -+ dev_err(priv->dev, -+ "Failed to enable core power: %d\n", ret); -+ return ret; -+ } -+ -+ regulator_set_voltage(priv->io_pwr, 3300000, 3300000); -+ ret = regulator_enable(priv->io_pwr); -+ if (ret < 0) { -+ dev_err(priv->dev, "Failed to enable io pwr: %d\n", -+ ret); -+ return ret; -+ } -+ -+ /* Reset whole chip through gpio pin or memory-mapped registers for -+ * different type of hardware -+ */ -+ if (priv->mcm) { -+ reset_control_assert(priv->rstc); -+ usleep_range(1000, 1100); -+ reset_control_deassert(priv->rstc); -+ } else { -+ gpiod_set_value_cansleep(priv->reset, 0); -+ usleep_range(1000, 1100); -+ gpiod_set_value_cansleep(priv->reset, 1); -+ } -+ -+ /* Waiting for MT7530 got to stable */ -+ ret = readx_poll_timeout(_mt7530_read, MT7530_HWTRAP, val, val != 0, -+ 20, 1000000); -+ if (ret < 0) { -+ dev_err(priv->dev, "reset timeout\n"); -+ return ret; -+ } -+ -+ id = mt7530_read(priv, MT7530_CREV); -+ id >>= CHIP_NAME_SHIFT; -+ if (id != MT7530_ID) { -+ dev_err(priv->dev, "chip %x can't be supported\n", id); -+ return -ENODEV; -+ } -+ -+ /* Reset the switch through internal reset */ -+ mt7530_write(priv, MT7530_SYS_CTRL, -+ SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST | -+ SYS_CTRL_REG_RST); -+ -+ /* Enable Port 6 only; P5 as GMAC5 which currently is not supported */ -+ val = mt7530_read(priv, MT7530_MHWTRAP); -+ val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; -+ val |= MHWTRAP_MANUAL; -+ mt7530_write(priv, MT7530_MHWTRAP, val); -+ -+ /* Enable and reset MIB counters */ -+ mt7530_mib_reset(ds); -+ -+ mt7530_clear(priv, MT7530_MFC, UNU_FFP_MASK); -+ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) { -+ /* Disable forwarding by default on all ports */ -+ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, -+ PCR_MATRIX_CLR); -+ -+ if (dsa_is_cpu_port(ds, i)) -+ mt7530_cpu_port_enable(priv, i); -+ else -+ mt7530_port_disable(ds, i, NULL); -+ } -+ -+ /* Flush the FDB table */ -+ ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, 0); -+ if (ret < 0) -+ return ret; -+ -+ return 0; -+} -+ -+static int mt7530_phy_read(struct dsa_switch *ds, int port, int regnum) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return mdiobus_read_nested(priv->bus, port, regnum); -+} -+ -+int mt7530_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ return mdiobus_write_nested(priv->bus, port, regnum, val); -+} -+ -+static void -+mt7530_get_strings(struct dsa_switch *ds, int port, uint8_t *data) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(mt7530_mib); i++) -+ strncpy(data + i * ETH_GSTRING_LEN, mt7530_mib[i].name, -+ ETH_GSTRING_LEN); -+} -+ -+static void -+mt7530_get_ethtool_stats(struct dsa_switch *ds, int port, -+ uint64_t *data) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ const struct mt7530_mib_desc *mib; -+ u32 reg, i; -+ u64 hi; -+ -+ for (i = 0; i < ARRAY_SIZE(mt7530_mib); i++) { -+ mib = &mt7530_mib[i]; -+ reg = MT7530_PORT_MIB_COUNTER(port) + mib->offset; -+ -+ data[i] = mt7530_read(priv, reg); -+ if (mib->size == 2) { -+ hi = mt7530_read(priv, reg + 4); -+ data[i] |= hi << 32; -+ } -+ } -+} -+ -+static int -+mt7530_get_sset_count(struct dsa_switch *ds) -+{ -+ return ARRAY_SIZE(mt7530_mib); -+} -+ -+static void mt7530_adjust_link(struct dsa_switch *ds, int port, -+ struct phy_device *phydev) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ if (phy_is_pseudo_fixed_link(phydev)) { -+ dev_dbg(priv->dev, "phy-mode for master device = %x\n", -+ phydev->interface); -+ -+ /* Setup TX circuit incluing relevant PAD and driving */ -+ mt7530_pad_clk_setup(ds, phydev->interface); -+ -+ /* Setup RX circuit, relevant PAD and driving on the host -+ * which must be placed after the setup on the device side is -+ * all finished. -+ */ -+ mt7623_pad_clk_setup(ds); -+ } -+} -+ -+static int -+mt7530_cpu_port_enable(struct mt7530_priv *priv, -+ int port) -+{ -+ /* Enable Mediatek header mode on the cpu port */ -+ mt7530_write(priv, MT7530_PVC_P(port), -+ PORT_SPEC_TAG); -+ -+ /* Setup the MAC by default for the cpu port */ -+ mt7530_write(priv, MT7530_PMCR_P(port), PMCR_CPUP_LINK); -+ -+ /* Disable auto learning on the cpu port */ -+ mt7530_set(priv, MT7530_PSC_P(port), SA_DIS); -+ -+ /* Unknown unicast frame fordwarding to the cpu port */ -+ mt7530_set(priv, MT7530_MFC, UNU_FFP(BIT(port))); -+ -+ /* CPU port gets connected to all user ports of -+ * the switch -+ */ -+ mt7530_write(priv, MT7530_PCR_P(port), -+ PCR_MATRIX(priv->ds->enabled_port_mask)); -+ -+ return 0; -+} -+ -+static int -+mt7530_port_enable(struct dsa_switch *ds, int port, -+ struct phy_device *phy) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ mutex_lock(&priv->reg_mutex); -+ -+ /* Setup the MAC for the user port */ -+ mt7530_write(priv, MT7530_PMCR_P(port), PMCR_USERP_LINK); -+ -+ /* Allow the user port gets connected to the cpu port and also -+ * restore the port matrix if the port is the member of a certain -+ * bridge. -+ */ -+ priv->ports[port].pm |= PCR_MATRIX(BIT(MT7530_CPU_PORT)); -+ priv->ports[port].enable = true; -+ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, -+ priv->ports[port].pm); -+ mt7530_port_set_status(priv, port, 1); -+ -+ mutex_unlock(&priv->reg_mutex); -+ -+ return 0; -+} -+ -+static void -+mt7530_port_disable(struct dsa_switch *ds, int port, -+ struct phy_device *phy) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ mutex_lock(&priv->reg_mutex); -+ -+ /* Clear up all port matrix which could be restored in the next -+ * enablement for the port. -+ */ -+ priv->ports[port].enable = false; -+ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, -+ PCR_MATRIX_CLR); -+ mt7530_port_set_status(priv, port, 0); -+ -+ mutex_unlock(&priv->reg_mutex); -+} -+ -+static void -+mt7530_stp_state_set(struct dsa_switch *ds, int port, u8 state) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ u32 stp_state; -+ -+ switch (state) { -+ case BR_STATE_DISABLED: -+ stp_state = MT7530_STP_DISABLED; -+ break; -+ case BR_STATE_BLOCKING: -+ stp_state = MT7530_STP_BLOCKING; -+ break; -+ case BR_STATE_LISTENING: -+ stp_state = MT7530_STP_LISTENING; -+ break; -+ case BR_STATE_LEARNING: -+ stp_state = MT7530_STP_LEARNING; -+ break; -+ case BR_STATE_FORWARDING: -+ default: -+ stp_state = MT7530_STP_FORWARDING; -+ break; -+ } -+ -+ mt7530_rmw(priv, MT7530_SSP_P(port), FID_PST_MASK, stp_state); -+} -+ -+static int -+mt7530_port_bridge_join(struct dsa_switch *ds, int port, -+ struct net_device *bridge) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ u32 port_bitmap = BIT(MT7530_CPU_PORT); -+ int i; -+ -+ mutex_lock(&priv->reg_mutex); -+ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) { -+ /* Add this port to the port matrix of the other ports in the -+ * same bridge. If the port is disabled, port matrix is kept -+ * and not being setup until the port becomes enabled. -+ */ -+ if (ds->enabled_port_mask & BIT(i) && i != port) { -+ if (ds->ports[i].bridge_dev != bridge) -+ continue; -+ if (priv->ports[i].enable) -+ mt7530_set(priv, MT7530_PCR_P(i), -+ PCR_MATRIX(BIT(port))); -+ priv->ports[i].pm |= PCR_MATRIX(BIT(port)); -+ -+ port_bitmap |= BIT(i); -+ } -+ } -+ -+ /* Add the all other ports to this port matrix. */ -+ if (priv->ports[port].enable) -+ mt7530_rmw(priv, MT7530_PCR_P(port), -+ PCR_MATRIX_MASK, PCR_MATRIX(port_bitmap)); -+ priv->ports[port].pm |= PCR_MATRIX(port_bitmap); -+ -+ mutex_unlock(&priv->reg_mutex); -+ -+ return 0; -+} -+ -+static void -+mt7530_port_bridge_leave(struct dsa_switch *ds, int port, -+ struct net_device *bridge) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ int i; -+ -+ mutex_lock(&priv->reg_mutex); -+ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) { -+ /* Remove this port from the port matrix of the other ports -+ * in the same bridge. If the port is disabled, port matrix -+ * is kept and not being setup until the port becomes enabled. -+ */ -+ if (ds->enabled_port_mask & BIT(i) && i != port) { -+ if (ds->ports[i].bridge_dev != bridge) -+ continue; -+ if (priv->ports[i].enable) -+ mt7530_clear(priv, MT7530_PCR_P(i), -+ PCR_MATRIX(BIT(port))); -+ priv->ports[i].pm &= ~PCR_MATRIX(BIT(port)); -+ } -+ } -+ -+ /* Set the cpu port to be the only one in the port matrix of -+ * this port. -+ */ -+ if (priv->ports[port].enable) -+ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, -+ PCR_MATRIX(BIT(MT7530_CPU_PORT))); -+ priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT)); -+ -+ mutex_unlock(&priv->reg_mutex); -+} -+ -+static int -+mt7530_port_fdb_prepare(struct dsa_switch *ds, int port, -+ const struct switchdev_obj_port_fdb *fdb, -+ struct switchdev_trans *trans) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ int ret; -+ -+ /* Because auto-learned entrie shares the same FDB table. -+ * an entry is reserved with no port_mask to make sure fdb_add -+ * is called while the entry is still available. -+ */ -+ mutex_lock(&priv->reg_mutex); -+ mt7530_fdb_write(priv, fdb->vid, 0, fdb->addr, -1, STATIC_ENT); -+ ret = mt7530_fdb_cmd(priv, MT7530_FDB_WRITE, 0); -+ mutex_unlock(&priv->reg_mutex); -+ -+ return ret; -+} -+ -+static void -+mt7530_port_fdb_add(struct dsa_switch *ds, int port, -+ const struct switchdev_obj_port_fdb *fdb, -+ struct switchdev_trans *trans) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ u8 port_mask = BIT(port); -+ -+ mutex_lock(&priv->reg_mutex); -+ mt7530_fdb_write(priv, fdb->vid, port_mask, fdb->addr, -1, STATIC_ENT); -+ mt7530_fdb_cmd(priv, MT7530_FDB_WRITE, 0); -+ mutex_unlock(&priv->reg_mutex); -+} -+ -+static int -+mt7530_port_fdb_del(struct dsa_switch *ds, int port, -+ const struct switchdev_obj_port_fdb *fdb) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ int ret; -+ u8 port_mask = BIT(port); -+ -+ mutex_lock(&priv->reg_mutex); -+ mt7530_fdb_write(priv, fdb->vid, port_mask, fdb->addr, -1, STATIC_EMP); -+ ret = mt7530_fdb_cmd(priv, MT7530_FDB_WRITE, 0); -+ mutex_unlock(&priv->reg_mutex); -+ -+ return ret; -+} -+ -+static int -+mt7530_port_fdb_dump(struct dsa_switch *ds, int port, -+ struct switchdev_obj_port_fdb *fdb, -+ int (*cb)(struct switchdev_obj *obj)) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ struct mt7530_fdb _fdb = { 0 }; -+ int cnt = MT7530_NUM_FDB_RECORDS; -+ int ret = 0; -+ u32 rsp = 0; -+ -+ mutex_lock(&priv->reg_mutex); -+ -+ ret = mt7530_fdb_cmd(priv, MT7530_FDB_START, &rsp); -+ if (ret < 0) -+ goto err; -+ -+ do { -+ if (rsp & ATC_SRCH_HIT) { -+ mt7530_fdb_read(priv, &_fdb); -+ if (_fdb.port_mask & BIT(port)) { -+ ether_addr_copy(fdb->addr, _fdb.mac); -+ fdb->vid = _fdb.vid; -+ fdb->ndm_state = _fdb.noarp ? -+ NUD_NOARP : NUD_REACHABLE; -+ ret = cb(&fdb->obj); -+ if (ret < 0) -+ break; -+ } -+ } -+ } while (--cnt && -+ !(rsp & ATC_SRCH_END) && -+ !mt7530_fdb_cmd(priv, MT7530_FDB_NEXT, &rsp)); -+err: -+ mutex_unlock(&priv->reg_mutex); -+ -+ return 0; -+} -+ -+static enum dsa_tag_protocol -+mtk_get_tag_protocol(struct dsa_switch *ds) -+{ -+ struct mt7530_priv *priv = ds->priv; -+ -+ if (!dsa_is_cpu_port(ds, MT7530_CPU_PORT)) { -+ dev_warn(priv->dev, -+ "port not matched with tagging CPU port\n"); -+ return DSA_TAG_PROTO_NONE; -+ } else { -+ return DSA_TAG_PROTO_MTK; -+ } -+} -+ -+static struct dsa_switch_ops mt7530_switch_ops = { -+ .get_tag_protocol = mtk_get_tag_protocol, -+ .setup = mt7530_setup, -+ .get_strings = mt7530_get_strings, -+ .phy_read = mt7530_phy_read, -+ .phy_write = mt7530_phy_write, -+ .get_ethtool_stats = mt7530_get_ethtool_stats, -+ .get_sset_count = mt7530_get_sset_count, -+ .adjust_link = mt7530_adjust_link, -+ .port_enable = mt7530_port_enable, -+ .port_disable = mt7530_port_disable, -+ .port_stp_state_set = mt7530_stp_state_set, -+ .port_bridge_join = mt7530_port_bridge_join, -+ .port_bridge_leave = mt7530_port_bridge_leave, -+ .port_fdb_prepare = mt7530_port_fdb_prepare, -+ .port_fdb_add = mt7530_port_fdb_add, -+ .port_fdb_del = mt7530_port_fdb_del, -+ .port_fdb_dump = mt7530_port_fdb_dump, -+}; -+ -+static int -+mt7530_probe(struct mdio_device *mdiodev) -+{ -+ struct mt7530_priv *priv; -+ struct device_node *dn; -+ -+ dn = mdiodev->dev.of_node; -+ -+ priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->ds = dsa_switch_alloc(&mdiodev->dev, DSA_MAX_PORTS); -+ if (!priv->ds) -+ return -ENOMEM; -+ -+ /* Use medatek,mcm property to distinguish hardware type that would -+ * casues a little bit differences on power-on sequence. -+ */ -+ priv->mcm = of_property_read_bool(dn, "mediatek,mcm"); -+ if (priv->mcm) { -+ dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n"); -+ -+ priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm"); -+ if (IS_ERR(priv->rstc)) { -+ dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); -+ return PTR_ERR(priv->rstc); -+ } -+ } -+ -+ priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); -+ if (IS_ERR(priv->core_pwr)) -+ return PTR_ERR(priv->core_pwr); -+ -+ priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); -+ if (IS_ERR(priv->io_pwr)) -+ return PTR_ERR(priv->io_pwr); -+ -+ /* Not MCM that indicates switch works as the remote standalone -+ * integrated circuit so the GPIO pin would be used to complete -+ * the reset, otherwise memory-mapped register accessing used -+ * through syscon provides in the case of MCM. -+ */ -+ if (!priv->mcm) { -+ priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset", -+ GPIOD_OUT_LOW); -+ if (IS_ERR(priv->reset)) { -+ dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); -+ return PTR_ERR(priv->reset); -+ } -+ } -+ -+ priv->bus = mdiodev->bus; -+ priv->dev = &mdiodev->dev; -+ priv->ds->priv = priv; -+ priv->ds->ops = &mt7530_switch_ops; -+ mutex_init(&priv->reg_mutex); -+ lpriv = priv; -+ dev_set_drvdata(&mdiodev->dev, priv); -+ -+ return dsa_register_switch(priv->ds, &mdiodev->dev); -+} -+ -+static void -+mt7530_remove(struct mdio_device *mdiodev) -+{ -+ struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); -+ int ret = 0; -+ -+ ret = regulator_disable(priv->core_pwr); -+ if (ret < 0) -+ dev_err(priv->dev, -+ "Failed to disable core power: %d\n", ret); -+ -+ ret = regulator_disable(priv->io_pwr); -+ if (ret < 0) -+ dev_err(priv->dev, "Failed to disable io pwr: %d\n", -+ ret); -+ -+ dsa_unregister_switch(priv->ds); -+ mutex_destroy(&priv->reg_mutex); -+} -+ -+static const struct of_device_id mt7530_of_match[] = { -+ { .compatible = "mediatek,mt7530" }, -+ { /* sentinel */ }, -+}; -+ -+static struct mdio_driver mt7530_mdio_driver = { -+ .probe = mt7530_probe, -+ .remove = mt7530_remove, -+ .mdiodrv.driver = { -+ .name = "mt7530", -+ .of_match_table = mt7530_of_match, -+ }, -+}; -+ -+mdio_module_driver(mt7530_mdio_driver); -+ -+MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); -+MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:mediatek-mt7530"); ---- /dev/null -+++ b/drivers/net/dsa/mt7530.h -@@ -0,0 +1,390 @@ -+/* -+ * 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 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. -+ */ -+ -+#ifndef __MT7530_H -+#define __MT7530_H -+ -+#define MT7530_NUM_PORTS 7 -+#define MT7530_CPU_PORT 6 -+#define MT7530_NUM_FDB_RECORDS 2048 -+ -+#define NUM_TRGMII_CTRL 5 -+ -+#define TRGMII_BASE(x) (0x10000 + (x)) -+ -+/* Registers to ethsys access */ -+#define ETHSYS_CLKCFG0 0x2c -+#define ETHSYS_TRGMII_CLK_SEL362_5 BIT(11) -+ -+#define SYSC_REG_RSTCTRL 0x34 -+#define RESET_MCM BIT(2) -+ -+/* Registers to mac forward control for unknown frames */ -+#define MT7530_MFC 0x10 -+#define BC_FFP(x) (((x) & 0xff) << 24) -+#define UNM_FFP(x) (((x) & 0xff) << 16) -+#define UNU_FFP(x) (((x) & 0xff) << 8) -+#define UNU_FFP_MASK UNU_FFP(~0) -+ -+/* Registers for address table access */ -+#define MT7530_ATA1 0x74 -+#define STATIC_EMP 0 -+#define STATIC_ENT 3 -+#define MT7530_ATA2 0x78 -+ -+/* Register for address table write data */ -+#define MT7530_ATWD 0x7c -+ -+/* Register for address table control */ -+#define MT7530_ATC 0x80 -+#define ATC_HASH (((x) & 0xfff) << 16) -+#define ATC_BUSY BIT(15) -+#define ATC_SRCH_END BIT(14) -+#define ATC_SRCH_HIT BIT(13) -+#define ATC_INVALID BIT(12) -+#define ATC_MAT(x) (((x) & 0xf) << 8) -+#define ATC_MAT_MACTAB ATC_MAT(0) -+ -+enum mt7530_fdb_cmd { -+ MT7530_FDB_READ = 0, -+ MT7530_FDB_WRITE = 1, -+ MT7530_FDB_FLUSH = 2, -+ MT7530_FDB_START = 4, -+ MT7530_FDB_NEXT = 5, -+}; -+ -+/* Registers for table search read address */ -+#define MT7530_TSRA1 0x84 -+#define MAC_BYTE_0 24 -+#define MAC_BYTE_1 16 -+#define MAC_BYTE_2 8 -+#define MAC_BYTE_3 0 -+#define MAC_BYTE_MASK 0xff -+ -+#define MT7530_TSRA2 0x88 -+#define MAC_BYTE_4 24 -+#define MAC_BYTE_5 16 -+#define CVID 0 -+#define CVID_MASK 0xfff -+ -+#define MT7530_ATRD 0x8C -+#define AGE_TIMER 24 -+#define AGE_TIMER_MASK 0xff -+#define PORT_MAP 4 -+#define PORT_MAP_MASK 0xff -+#define ENT_STATUS 2 -+#define ENT_STATUS_MASK 0x3 -+ -+/* Register for vlan table control */ -+#define MT7530_VTCR 0x90 -+#define VTCR_BUSY BIT(31) -+#define VTCR_FUNC (((x) & 0xf) << 12) -+#define VTCR_FUNC_RD_VID 0x1 -+#define VTCR_FUNC_WR_VID 0x2 -+#define VTCR_FUNC_INV_VID 0x3 -+#define VTCR_FUNC_VAL_VID 0x4 -+#define VTCR_VID ((x) & 0xfff) -+ -+/* Register for setup vlan and acl write data */ -+#define MT7530_VAWD1 0x94 -+#define PORT_STAG BIT(31) -+#define IVL_MAC BIT(30) -+#define PORT_MEM(x) (((x) & 0xff) << 16) -+#define VALID BIT(1) -+ -+#define MT7530_VAWD2 0x98 -+ -+/* Register for port STP state control */ -+#define MT7530_SSP_P(x) (0x2000 + ((x) * 0x100)) -+#define FID_PST(x) ((x) & 0x3) -+#define FID_PST_MASK FID_PST(0x3) -+ -+enum mt7530_stp_state { -+ MT7530_STP_DISABLED = 0, -+ MT7530_STP_BLOCKING = 1, -+ MT7530_STP_LISTENING = 1, -+ MT7530_STP_LEARNING = 2, -+ MT7530_STP_FORWARDING = 3 -+}; -+ -+/* Register for port control */ -+#define MT7530_PCR_P(x) (0x2004 + ((x) * 0x100)) -+#define PORT_VLAN(x) ((x) & 0x3) -+#define PCR_MATRIX(x) (((x) & 0xff) << 16) -+#define PORT_PRI(x) (((x) & 0x7) << 24) -+#define EG_TAG(x) (((x) & 0x3) << 28) -+#define PCR_MATRIX_MASK PCR_MATRIX(0xff) -+#define PCR_MATRIX_CLR PCR_MATRIX(0) -+ -+/* Register for port security control */ -+#define MT7530_PSC_P(x) (0x200c + ((x) * 0x100)) -+#define SA_DIS BIT(4) -+ -+/* Register for port vlan control */ -+#define MT7530_PVC_P(x) (0x2010 + ((x) * 0x100)) -+#define PORT_SPEC_TAG BIT(5) -+#define VLAN_ATTR(x) (((x) & 0x3) << 6) -+#define STAG_VPID (((x) & 0xffff) << 16) -+ -+/* Register for port port-and-protocol based vlan 1 control */ -+#define MT7530_PPBV1_P(x) (0x2014 + ((x) * 0x100)) -+ -+/* Register for port MAC control register */ -+#define MT7530_PMCR_P(x) (0x3000 + ((x) * 0x100)) -+#define PMCR_IFG_XMIT(x) (((x) & 0x3) << 18) -+#define PMCR_MAC_MODE BIT(16) -+#define PMCR_FORCE_MODE BIT(15) -+#define PMCR_TX_EN BIT(14) -+#define PMCR_RX_EN BIT(13) -+#define PMCR_BACKOFF_EN BIT(9) -+#define PMCR_BACKPR_EN BIT(8) -+#define PMCR_TX_FC_EN BIT(5) -+#define PMCR_RX_FC_EN BIT(4) -+#define PMCR_FORCE_SPEED_1000 BIT(3) -+#define PMCR_FORCE_FDX BIT(1) -+#define PMCR_FORCE_LNK BIT(0) -+#define PMCR_COMMON_LINK (PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \ -+ PMCR_BACKOFF_EN | PMCR_BACKPR_EN | \ -+ PMCR_TX_EN | PMCR_RX_EN | \ -+ PMCR_TX_FC_EN | PMCR_RX_FC_EN) -+#define PMCR_CPUP_LINK (PMCR_COMMON_LINK | PMCR_FORCE_MODE | \ -+ PMCR_FORCE_SPEED_1000 | \ -+ PMCR_FORCE_FDX | \ -+ PMCR_FORCE_LNK) -+#define PMCR_USERP_LINK PMCR_COMMON_LINK -+#define PMCR_FIXED_LINK (PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \ -+ PMCR_FORCE_MODE | PMCR_TX_EN | \ -+ PMCR_RX_EN | PMCR_BACKPR_EN | \ -+ PMCR_BACKOFF_EN | \ -+ PMCR_FORCE_SPEED_1000 | \ -+ PMCR_FORCE_FDX | \ -+ PMCR_FORCE_LNK) -+#define PMCR_FIXED_LINK_FC (PMCR_FIXED_LINK | \ -+ PMCR_TX_FC_EN | PMCR_RX_FC_EN) -+ -+#define MT7530_PMSR_P(x) (0x3008 + (x) * 0x100) -+ -+/* Register for MIB */ -+#define MT7530_PORT_MIB_COUNTER(x) (0x4000 + (x) * 0x100) -+#define MT7530_MIB_CCR 0x4fe0 -+#define CCR_MIB_ENABLE BIT(31) -+#define CCR_RX_OCT_CNT_GOOD BIT(7) -+#define CCR_RX_OCT_CNT_BAD BIT(6) -+#define CCR_TX_OCT_CNT_GOOD BIT(5) -+#define CCR_TX_OCT_CNT_BAD BIT(4) -+#define CCR_MIB_FLUSH (CCR_RX_OCT_CNT_GOOD | \ -+ CCR_RX_OCT_CNT_BAD | \ -+ CCR_TX_OCT_CNT_GOOD | \ -+ CCR_TX_OCT_CNT_BAD) -+#define CCR_MIB_ACTIVATE (CCR_MIB_ENABLE | \ -+ CCR_RX_OCT_CNT_GOOD | \ -+ CCR_RX_OCT_CNT_BAD | \ -+ CCR_TX_OCT_CNT_GOOD | \ -+ CCR_TX_OCT_CNT_BAD) -+/* Register for system reset */ -+#define MT7530_SYS_CTRL 0x7000 -+#define SYS_CTRL_PHY_RST BIT(2) -+#define SYS_CTRL_SW_RST BIT(1) -+#define SYS_CTRL_REG_RST BIT(0) -+ -+/* Register for hw trap status */ -+#define MT7530_HWTRAP 0x7800 -+ -+/* Register for hw trap modification */ -+#define MT7530_MHWTRAP 0x7804 -+#define MHWTRAP_MANUAL BIT(16) -+#define MHWTRAP_P5_MAC_SEL BIT(13) -+#define MHWTRAP_P6_DIS BIT(8) -+#define MHWTRAP_P5_RGMII_MODE BIT(7) -+#define MHWTRAP_P5_DIS BIT(6) -+#define MHWTRAP_PHY_ACCESS BIT(5) -+ -+/* Register for TOP signal control */ -+#define MT7530_TOP_SIG_CTRL 0x7808 -+#define TOP_SIG_CTRL_NORMAL (BIT(17) | BIT(16)) -+ -+#define MT7530_IO_DRV_CR 0x7810 -+#define P5_IO_CLK_DRV(x) ((x) & 0x3) -+#define P5_IO_DATA_DRV(x) (((x) & 0x3) << 4) -+ -+#define MT7530_P6ECR 0x7830 -+#define P6_INTF_MODE_MASK 0x3 -+#define P6_INTF_MODE(x) ((x) & 0x3) -+ -+/* Registers for TRGMII on the both side */ -+#define MT7530_TRGMII_RCK_CTRL 0x7a00 -+#define GSW_TRGMII_RCK_CTRL 0x300 -+#define RX_RST BIT(31) -+#define RXC_DQSISEL BIT(30) -+#define DQSI1_TAP_MASK (0x7f << 8) -+#define DQSI0_TAP_MASK 0x7f -+#define DQSI1_TAP(x) (((x) & 0x7f) << 8) -+#define DQSI0_TAP(x) ((x) & 0x7f) -+ -+#define MT7530_TRGMII_RCK_RTT 0x7a04 -+#define GSW_TRGMII_RCK_RTT 0x304 -+#define DQS1_GATE BIT(31) -+#define DQS0_GATE BIT(30) -+ -+#define MT7530_TRGMII_RD(x) (0x7a10 + (x) * 8) -+#define GSW_TRGMII_RD(x) (0x310 + (x) * 8) -+#define BSLIP_EN BIT(31) -+#define EDGE_CHK BIT(30) -+#define RD_TAP_MASK 0x7f -+#define RD_TAP(x) ((x) & 0x7f) -+ -+#define GSW_TRGMII_TXCTRL 0x340 -+#define MT7530_TRGMII_TXCTRL 0x7a40 -+#define TRAIN_TXEN BIT(31) -+#define TXC_INV BIT(30) -+#define TX_RST BIT(28) -+ -+#define MT7530_TRGMII_TD_ODT(i) (0x7a54 + 8 * (i)) -+#define GSW_TRGMII_TD_ODT(i) (0x354 + 8 * (i)) -+#define TD_DM_DRVP(x) ((x) & 0xf) -+#define TD_DM_DRVN(x) (((x) & 0xf) << 4) -+ -+#define GSW_INTF_MODE 0x390 -+#define INTF_MODE_TRGMII BIT(1) -+ -+#define MT7530_TRGMII_TCK_CTRL 0x7a78 -+#define TCK_TAP(x) (((x) & 0xf) << 8) -+ -+#define MT7530_P5RGMIIRXCR 0x7b00 -+#define CSR_RGMII_EDGE_ALIGN BIT(8) -+#define CSR_RGMII_RXC_0DEG_CFG(x) ((x) & 0xf) -+ -+#define MT7530_P5RGMIITXCR 0x7b04 -+#define CSR_RGMII_TXC_CFG(x) ((x) & 0x1f) -+ -+#define MT7530_CREV 0x7ffc -+#define CHIP_NAME_SHIFT 16 -+#define MT7530_ID 0x7530 -+ -+/* Registers for core PLL access through mmd indirect */ -+#define CORE_PLL_GROUP2 0x401 -+#define RG_SYSPLL_EN_NORMAL BIT(15) -+#define RG_SYSPLL_VODEN BIT(14) -+#define RG_SYSPLL_LF BIT(13) -+#define RG_SYSPLL_RST_DLY(x) (((x) & 0x3) << 12) -+#define RG_SYSPLL_LVROD_EN BIT(10) -+#define RG_SYSPLL_PREDIV(x) (((x) & 0x3) << 8) -+#define RG_SYSPLL_POSDIV(x) (((x) & 0x3) << 5) -+#define RG_SYSPLL_FBKSEL BIT(4) -+#define RT_SYSPLL_EN_AFE_OLT BIT(0) -+ -+#define CORE_PLL_GROUP4 0x403 -+#define RG_SYSPLL_DDSFBK_EN BIT(12) -+#define RG_SYSPLL_BIAS_EN BIT(11) -+#define RG_SYSPLL_BIAS_LPF_EN BIT(10) -+ -+#define CORE_PLL_GROUP5 0x404 -+#define RG_LCDDS_PCW_NCPO1(x) ((x) & 0xffff) -+ -+#define CORE_PLL_GROUP6 0x405 -+#define RG_LCDDS_PCW_NCPO0(x) ((x) & 0xffff) -+ -+#define CORE_PLL_GROUP7 0x406 -+#define RG_LCDDS_PWDB BIT(15) -+#define RG_LCDDS_ISO_EN BIT(13) -+#define RG_LCCDS_C(x) (((x) & 0x7) << 4) -+#define RG_LCDDS_PCW_NCPO_CHG BIT(3) -+ -+#define CORE_PLL_GROUP10 0x409 -+#define RG_LCDDS_SSC_DELTA(x) ((x) & 0xfff) -+ -+#define CORE_PLL_GROUP11 0x40a -+#define RG_LCDDS_SSC_DELTA1(x) ((x) & 0xfff) -+ -+#define CORE_GSWPLL_GRP1 0x40d -+#define RG_GSWPLL_PREDIV(x) (((x) & 0x3) << 14) -+#define RG_GSWPLL_POSDIV_200M(x) (((x) & 0x3) << 12) -+#define RG_GSWPLL_EN_PRE BIT(11) -+#define RG_GSWPLL_FBKSEL BIT(10) -+#define RG_GSWPLL_BP BIT(9) -+#define RG_GSWPLL_BR BIT(8) -+#define RG_GSWPLL_FBKDIV_200M(x) ((x) & 0xff) -+ -+#define CORE_GSWPLL_GRP2 0x40e -+#define RG_GSWPLL_POSDIV_500M(x) (((x) & 0x3) << 8) -+#define RG_GSWPLL_FBKDIV_500M(x) ((x) & 0xff) -+ -+#define CORE_TRGMII_GSW_CLK_CG 0x410 -+#define REG_GSWCK_EN BIT(0) -+#define REG_TRGMIICK_EN BIT(1) -+ -+#define MIB_DESC(_s, _o, _n) \ -+ { \ -+ .size = (_s), \ -+ .offset = (_o), \ -+ .name = (_n), \ -+ } -+ -+struct mt7530_mib_desc { -+ unsigned int size; -+ unsigned int offset; -+ const char *name; -+}; -+ -+struct mt7530_fdb { -+ u16 vid; -+ u8 port_mask; -+ u8 aging; -+ u8 mac[6]; -+ bool noarp; -+}; -+ -+struct mt7530_port { -+ bool enable; -+ u32 pm; -+}; -+ -+/* struct mt7530_priv - This is the main data structure for holding the state -+ * of the driver -+ * @dev: The device pointer -+ * @ds: The pointer to the dsa core structure -+ * @bus: The bus used for the device and built-in PHY -+ * @rstc: The pointer to reset control used by MCM -+ * @ethernet: The regmap used for access TRGMII-based registers -+ * @core_pwr: The power supplied into the core -+ * @io_pwr: The power supplied into the I/O -+ * @reset: The descriptor for GPIO line tied to its reset pin -+ * @mcm: Flag for distinguishing if standalone IC or module -+ * coupling -+ * @ports: Holding the state among ports -+ * @reg_mutex: The lock for protecting among process accessing -+ * registers -+ */ -+struct mt7530_priv { -+ struct device *dev; -+ struct dsa_switch *ds; -+ struct mii_bus *bus; -+ struct reset_control *rstc; -+ struct regmap *ethernet; -+ struct regulator *core_pwr; -+ struct regulator *io_pwr; -+ struct gpio_desc *reset; -+ bool mcm; -+ -+ struct mt7530_port ports[MT7530_NUM_PORTS]; -+ /* protect among processes for registers access*/ -+ struct mutex reg_mutex; -+}; -+ -+struct mt7530_hw_stats { -+ const char *string; -+ u16 reg; -+ u8 sizeof_stat; -+}; -+ -+#endif /* __MT7530_H */ diff --git a/target/linux/mediatek/patches-4.9/0031-net-dsa-dsa-api-compat.patch b/target/linux/mediatek/patches-4.9/0031-net-dsa-dsa-api-compat.patch deleted file mode 100644 index 9e52be8..0000000 --- a/target/linux/mediatek/patches-4.9/0031-net-dsa-dsa-api-compat.patch +++ /dev/null @@ -1,106 +0,0 @@ -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 - int i; - - mutex_lock(&priv->reg_mutex); -+ priv->bridge_dev[port] = bridge; - - for (i = 0; i < MT7530_NUM_PORTS; i++) { - /* Add this port to the port matrix of the other ports in the -@@ -841,7 +842,7 @@ mt7530_port_bridge_join(struct dsa_switc - * and not being setup until the port becomes enabled. - */ - if (ds->enabled_port_mask & BIT(i) && i != port) { -- if (ds->ports[i].bridge_dev != bridge) -+ if (priv->bridge_dev[i] != bridge) - continue; - if (priv->ports[i].enable) - mt7530_set(priv, MT7530_PCR_P(i), -@@ -864,8 +865,7 @@ mt7530_port_bridge_join(struct dsa_switc - } - - static void --mt7530_port_bridge_leave(struct dsa_switch *ds, int port, -- struct net_device *bridge) -+mt7530_port_bridge_leave(struct dsa_switch *ds, int port) - { - struct mt7530_priv *priv = ds->priv; - int i; -@@ -878,7 +878,7 @@ mt7530_port_bridge_leave(struct dsa_swit - * is kept and not being setup until the port becomes enabled. - */ - if (ds->enabled_port_mask & BIT(i) && i != port) { -- if (ds->ports[i].bridge_dev != bridge) -+ if (priv->bridge_dev[i] != priv->bridge_dev[port]) - continue; - if (priv->ports[i].enable) - mt7530_clear(priv, MT7530_PCR_P(i), -@@ -890,6 +890,7 @@ mt7530_port_bridge_leave(struct dsa_swit - /* Set the cpu port to be the only one in the port matrix of - * this port. - */ -+ priv->bridge_dev[port] = NULL; - if (priv->ports[port].enable) - mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, - PCR_MATRIX(BIT(MT7530_CPU_PORT))); -@@ -1033,7 +1034,7 @@ mt7530_probe(struct mdio_device *mdiodev - if (!priv) - return -ENOMEM; - -- priv->ds = dsa_switch_alloc(&mdiodev->dev, DSA_MAX_PORTS); -+ priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL); - if (!priv->ds) - return -ENOMEM; - -@@ -1076,12 +1077,13 @@ mt7530_probe(struct mdio_device *mdiodev - priv->bus = mdiodev->bus; - priv->dev = &mdiodev->dev; - priv->ds->priv = priv; -+ priv->ds->dev = &mdiodev->dev; - priv->ds->ops = &mt7530_switch_ops; - mutex_init(&priv->reg_mutex); - lpriv = priv; - dev_set_drvdata(&mdiodev->dev, priv); - -- return dsa_register_switch(priv->ds, &mdiodev->dev); -+ return dsa_register_switch(priv->ds, priv->ds->dev->of_node); - } - - static void ---- a/drivers/net/dsa/mt7530.h -+++ b/drivers/net/dsa/mt7530.h -@@ -379,6 +379,8 @@ struct mt7530_priv { - struct mt7530_port ports[MT7530_NUM_PORTS]; - /* protect among processes for registers access*/ - struct mutex reg_mutex; -+ -+ struct net_device *bridge_dev[MT7530_NUM_PORTS]; - }; - - struct mt7530_hw_stats { ---- a/net/dsa/tag_mtk.c -+++ b/net/dsa/tag_mtk.c -@@ -35,7 +35,7 @@ static struct sk_buff *mtk_tag_xmit(stru - /* Build the tag after the MAC Source Address */ - mtk_tag = skb->data + 2 * ETH_ALEN; - mtk_tag[0] = 0; -- mtk_tag[1] = (1 << p->dp->index) & MTK_HDR_XMIT_DP_BIT_MASK; -+ mtk_tag[1] = (1 << p->port) & MTK_HDR_XMIT_DP_BIT_MASK; - mtk_tag[2] = 0; - mtk_tag[3] = 0; - diff --git a/target/linux/mediatek/patches-4.9/0032-net-dsa-mediatek-add-support-for-GMAC2-wired-to-ext-.patch b/target/linux/mediatek/patches-4.9/0032-net-dsa-mediatek-add-support-for-GMAC2-wired-to-ext-.patch deleted file mode 100644 index 6c96b06..0000000 --- a/target/linux/mediatek/patches-4.9/0032-net-dsa-mediatek-add-support-for-GMAC2-wired-to-ext-.patch +++ /dev/null @@ -1,38 +0,0 @@ -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) - val = mt7530_read(priv, MT7530_MHWTRAP); - val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; - val |= MHWTRAP_MANUAL; -+ if (!dsa_is_cpu_port(ds, 5)) { -+ val |= MHWTRAP_P5_DIS; -+ val |= MHWTRAP_P5_MAC_SEL; -+ val |= MHWTRAP_P5_RGMII_MODE; -+ } - mt7530_write(priv, MT7530_MHWTRAP, val); - - /* Enable and reset MIB counters */ ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -221,6 +221,9 @@ static void mtk_phy_link_adjust(struct n - netif_carrier_on(dev); - else - netif_carrier_off(dev); -+ -+ if (!of_phy_is_fixed_link(mac->of_node)) -+ phy_print_status(dev->phydev); - } - - static int mtk_phy_connect_node(struct mtk_eth *eth, struct mtk_mac *mac, diff --git a/target/linux/mediatek/patches-4.9/0033-net-dsa-add-multi-gmac-support.patch b/target/linux/mediatek/patches-4.9/0033-net-dsa-add-multi-gmac-support.patch deleted file mode 100644 index 8ff2bed..0000000 --- a/target/linux/mediatek/patches-4.9/0033-net-dsa-add-multi-gmac-support.patch +++ /dev/null @@ -1,272 +0,0 @@ -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: - static enum dsa_tag_protocol - mtk_get_tag_protocol(struct dsa_switch *ds) - { -- struct mt7530_priv *priv = ds->priv; -- -- if (!dsa_is_cpu_port(ds, MT7530_CPU_PORT)) { -- dev_warn(priv->dev, -- "port not matched with tagging CPU port\n"); -- return DSA_TAG_PROTO_NONE; -- } else { -- return DSA_TAG_PROTO_MTK; -- } -+ return DSA_TAG_PROTO_MTK; - } - - static struct dsa_switch_ops mt7530_switch_ops = { ---- a/include/net/dsa.h -+++ b/include/net/dsa.h -@@ -145,6 +145,8 @@ struct dsa_port { - struct device_node *dn; - unsigned int ageing_time; - u8 stp_state; -+ struct net_device *ethernet; -+ int upstream; - }; - - struct dsa_switch { -@@ -205,7 +207,7 @@ struct dsa_switch { - - static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p) - { -- return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port); -+ return !!(ds->cpu_port_mask & (1 << p)); - } - - static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p) -@@ -218,6 +220,11 @@ static inline bool dsa_is_port_initializ - return ds->enabled_port_mask & (1 << p) && ds->ports[p].netdev; - } - -+static inline bool dsa_is_upstream_port(struct dsa_switch *ds, int p) -+{ -+ return dsa_is_cpu_port(ds, p) || dsa_is_dsa_port(ds, p); -+} -+ - static inline u8 dsa_upstream_port(struct dsa_switch *ds) - { - struct dsa_switch_tree *dst = ds->dst; -@@ -234,6 +241,18 @@ static inline u8 dsa_upstream_port(struc - return ds->rtable[dst->cpu_switch]; - } - -+static inline u8 dsa_port_upstream_port(struct dsa_switch *ds, int port) -+{ -+ /* -+ * If this port has a specific upstream cpu port, use it, -+ * otherwise use the switch default. -+ */ -+ if (ds->ports[port].upstream) -+ return ds->ports[port].upstream; -+ else -+ return dsa_upstream_port(ds); -+} -+ - struct switchdev_trans; - struct switchdev_obj; - struct switchdev_obj_port_fdb; ---- a/net/dsa/dsa2.c -+++ b/net/dsa/dsa2.c -@@ -248,8 +248,6 @@ static int dsa_cpu_port_apply(struct dev - return err; - } - -- ds->cpu_port_mask |= BIT(index); -- - return 0; - } - -@@ -259,6 +257,10 @@ static void dsa_cpu_port_unapply(struct - dsa_cpu_dsa_destroy(port); - ds->cpu_port_mask &= ~BIT(index); - -+ if (ds->ports[index].ethernet) { -+ dev_put(ds->ports[index].ethernet); -+ ds->ports[index].ethernet = NULL; -+ } - } - - static int dsa_user_port_apply(struct device_node *port, u32 index, -@@ -479,6 +481,29 @@ static int dsa_cpu_parse(struct device_n - - dst->rcv = dst->tag_ops->rcv; - -+ dev_hold(ethernet_dev); -+ ds->ports[index].ethernet = ethernet_dev; -+ ds->cpu_port_mask |= BIT(index); -+ -+ return 0; -+} -+ -+static int dsa_user_parse(struct device_node *port, u32 index, -+ struct dsa_switch *ds) -+{ -+ struct device_node *cpu_port; -+ const unsigned int *cpu_port_reg; -+ int cpu_port_index; -+ -+ cpu_port = of_parse_phandle(port, "cpu", 0); -+ if (cpu_port) { -+ cpu_port_reg = of_get_property(cpu_port, "reg", NULL); -+ if (!cpu_port_reg) -+ return -EINVAL; -+ cpu_port_index = be32_to_cpup(cpu_port_reg); -+ ds->ports[index].upstream = cpu_port_index; -+ } -+ - return 0; - } - -@@ -486,18 +511,19 @@ static int dsa_ds_parse(struct dsa_switc - { - struct device_node *port; - u32 index; -- int err; -+ int err = 0; - - for (index = 0; index < DSA_MAX_PORTS; index++) { - port = ds->ports[index].dn; - if (!port) - continue; - -- if (dsa_port_is_cpu(port)) { -+ if (dsa_port_is_cpu(port)) - err = dsa_cpu_parse(port, index, dst, ds); -- if (err) -- return err; -- } -+ else if (!dsa_port_is_dsa(port)) -+ err = dsa_user_parse(port, index, ds); -+ if (err) -+ return err; - } - - pr_info("DSA: switch %d %d parsed\n", dst->tree, ds->index); ---- a/net/dsa/dsa_priv.h -+++ b/net/dsa/dsa_priv.h -@@ -43,6 +43,7 @@ struct dsa_slave_priv { - int old_duplex; - - struct net_device *bridge_dev; -+ struct net_device *master; - #ifdef CONFIG_NET_POLL_CONTROLLER - struct netpoll *netpoll; - #endif ---- a/net/dsa/slave.c -+++ b/net/dsa/slave.c -@@ -61,7 +61,7 @@ static int dsa_slave_get_iflink(const st - { - struct dsa_slave_priv *p = netdev_priv(dev); - -- return p->parent->dst->master_netdev->ifindex; -+ return p->master->ifindex; - } - - static inline bool dsa_port_is_bridged(struct dsa_slave_priv *p) -@@ -96,7 +96,7 @@ static void dsa_port_set_stp_state(struc - static int dsa_slave_open(struct net_device *dev) - { - struct dsa_slave_priv *p = netdev_priv(dev); -- struct net_device *master = p->parent->dst->master_netdev; -+ struct net_device *master = p->master; - struct dsa_switch *ds = p->parent; - u8 stp_state = dsa_port_is_bridged(p) ? - BR_STATE_BLOCKING : BR_STATE_FORWARDING; -@@ -151,7 +151,7 @@ out: - static int dsa_slave_close(struct net_device *dev) - { - struct dsa_slave_priv *p = netdev_priv(dev); -- struct net_device *master = p->parent->dst->master_netdev; -+ struct net_device *master = p->master; - struct dsa_switch *ds = p->parent; - - if (p->phy) -@@ -178,7 +178,7 @@ static int dsa_slave_close(struct net_de - static void dsa_slave_change_rx_flags(struct net_device *dev, int change) - { - struct dsa_slave_priv *p = netdev_priv(dev); -- struct net_device *master = p->parent->dst->master_netdev; -+ struct net_device *master = p->master; - - if (change & IFF_ALLMULTI) - dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1); -@@ -189,7 +189,7 @@ static void dsa_slave_change_rx_flags(st - static void dsa_slave_set_rx_mode(struct net_device *dev) - { - struct dsa_slave_priv *p = netdev_priv(dev); -- struct net_device *master = p->parent->dst->master_netdev; -+ struct net_device *master = p->master; - - dev_mc_sync(master, dev); - dev_uc_sync(master, dev); -@@ -198,7 +198,7 @@ static void dsa_slave_set_rx_mode(struct - static int dsa_slave_set_mac_address(struct net_device *dev, void *a) - { - struct dsa_slave_priv *p = netdev_priv(dev); -- struct net_device *master = p->parent->dst->master_netdev; -+ struct net_device *master = p->master; - struct sockaddr *addr = a; - int err; - -@@ -633,7 +633,7 @@ static netdev_tx_t dsa_slave_xmit(struct - /* Queue the SKB for transmission on the parent interface, but - * do not modify its EtherType - */ -- nskb->dev = p->parent->dst->master_netdev; -+ nskb->dev = p->master; - dev_queue_xmit(nskb); - - return NETDEV_TX_OK; -@@ -945,7 +945,7 @@ static int dsa_slave_netpoll_setup(struc - { - struct dsa_slave_priv *p = netdev_priv(dev); - struct dsa_switch *ds = p->parent; -- struct net_device *master = ds->dst->master_netdev; -+ struct net_device *master = p->master; - struct netpoll *netpoll; - int err = 0; - -@@ -1233,11 +1233,16 @@ int dsa_slave_create(struct dsa_switch * - struct net_device *master; - struct net_device *slave_dev; - struct dsa_slave_priv *p; -+ int port_cpu = ds->ports[port].upstream; - int ret; - -- master = ds->dst->master_netdev; -- if (ds->master_netdev) -+ if (port_cpu && ds->ports[port_cpu].ethernet) -+ master = ds->ports[port_cpu].ethernet; -+ else if (ds->master_netdev) - master = ds->master_netdev; -+ else -+ master = ds->dst->master_netdev; -+ master->dsa_ptr = (void *)ds->dst; - - slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), name, - NET_NAME_UNKNOWN, ether_setup); -@@ -1263,6 +1268,7 @@ int dsa_slave_create(struct dsa_switch * - p->parent = ds; - p->port = port; - p->xmit = dst->tag_ops->xmit; -+ p->master = master; - - p->old_pause = -1; - p->old_link = -1; diff --git a/target/linux/mediatek/patches-4.9/0034-net-dsa-mediatek-add-dual-gmac-support.patch b/target/linux/mediatek/patches-4.9/0034-net-dsa-mediatek-add-dual-gmac-support.patch deleted file mode 100644 index ae06146..0000000 --- a/target/linux/mediatek/patches-4.9/0034-net-dsa-mediatek-add-dual-gmac-support.patch +++ /dev/null @@ -1,91 +0,0 @@ -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) - - /* Enable Port 6 only; P5 as GMAC5 which currently is not supported */ - val = mt7530_read(priv, MT7530_MHWTRAP); -- val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; -+ val &= ~MHWTRAP_P5_DIS & ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS; - val |= MHWTRAP_MANUAL; - if (!dsa_is_cpu_port(ds, 5)) { - val |= MHWTRAP_P5_DIS; -@@ -735,6 +735,9 @@ static int - mt7530_cpu_port_enable(struct mt7530_priv *priv, - int port) - { -+ u8 port_mask = 0; -+ int i; -+ - /* Enable Mediatek header mode on the cpu port */ - mt7530_write(priv, MT7530_PVC_P(port), - PORT_SPEC_TAG); -@@ -751,8 +754,12 @@ mt7530_cpu_port_enable(struct mt7530_pri - /* CPU port gets connected to all user ports of - * the switch - */ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) -+ if ((priv->ds->enabled_port_mask & BIT(i)) && -+ (dsa_port_upstream_port(priv->ds, i) == port)) -+ port_mask |= BIT(i); - mt7530_write(priv, MT7530_PCR_P(port), -- PCR_MATRIX(priv->ds->enabled_port_mask)); -+ PCR_MATRIX(port_mask)); - - return 0; - } -@@ -762,6 +769,7 @@ mt7530_port_enable(struct dsa_switch *ds - struct phy_device *phy) - { - struct mt7530_priv *priv = ds->priv; -+ u8 upstream = dsa_port_upstream_port(ds, port); - - mutex_lock(&priv->reg_mutex); - -@@ -772,7 +780,7 @@ mt7530_port_enable(struct dsa_switch *ds - * restore the port matrix if the port is the member of a certain - * bridge. - */ -- priv->ports[port].pm |= PCR_MATRIX(BIT(MT7530_CPU_PORT)); -+ priv->ports[port].pm |= PCR_MATRIX(BIT(upstream)); - priv->ports[port].enable = true; - mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, - priv->ports[port].pm); -@@ -835,7 +843,8 @@ mt7530_port_bridge_join(struct dsa_switc - struct net_device *bridge) - { - struct mt7530_priv *priv = ds->priv; -- u32 port_bitmap = BIT(MT7530_CPU_PORT); -+ u8 upstream = dsa_port_upstream_port(ds, port); -+ u32 port_bitmap = BIT(upstream); - int i; - - mutex_lock(&priv->reg_mutex); -@@ -873,6 +882,7 @@ static void - mt7530_port_bridge_leave(struct dsa_switch *ds, int port) - { - struct mt7530_priv *priv = ds->priv; -+ u8 upstream = dsa_port_upstream_port(ds, port); - int i; - - mutex_lock(&priv->reg_mutex); -@@ -898,8 +908,8 @@ mt7530_port_bridge_leave(struct dsa_swit - priv->bridge_dev[port] = NULL; - if (priv->ports[port].enable) - mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK, -- PCR_MATRIX(BIT(MT7530_CPU_PORT))); -- priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT)); -+ PCR_MATRIX(BIT(upstream))); -+ priv->ports[port].pm = PCR_MATRIX(BIT(upstream)); - - mutex_unlock(&priv->reg_mutex); - } 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 deleted file mode 100644 index 36321c5..0000000 --- a/target/linux/mediatek/patches-4.9/0035-net-mediatek-disable-RX-VLan-offloading.patch +++ /dev/null @@ -1,47 +0,0 @@ -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 deleted file mode 100644 index e96374f..0000000 --- a/target/linux/mediatek/patches-4.9/0036-net-next-mediatek-fix-typos-inside-the-header-file.patch +++ /dev/null @@ -1,25 +0,0 @@ -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 deleted file mode 100644 index 9d6a089..0000000 --- a/target/linux/mediatek/patches-4.9/0037-net-next-mediatek-bring-up-QDMA-RX-ring-0.patch +++ /dev/null @@ -1,128 +0,0 @@ -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 deleted file mode 100644 index cb1c1b9..0000000 --- a/target/linux/mediatek/patches-4.9/0038-net-next-dsa-move-struct-dsa_device_ops-to-the-globa.patch +++ /dev/null @@ -1,46 +0,0 @@ -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 deleted file mode 100644 index ebc52c8..0000000 --- a/target/linux/mediatek/patches-4.9/0039-net-next-dsa-add-flow_dissect-callback-to-struct-dsa.patch +++ /dev/null @@ -1,32 +0,0 @@ -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 deleted file mode 100644 index da98a21..0000000 --- a/target/linux/mediatek/patches-4.9/0040-net-next-tag_mtk-add-flow_dissect-callback-to-the-op.patch +++ /dev/null @@ -1,39 +0,0 @@ -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 deleted file mode 100644 index 5435962..0000000 --- a/target/linux/mediatek/patches-4.9/0041-net-next-dsa-fix-flow-dissection.patch +++ /dev/null @@ -1,65 +0,0 @@ -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 deleted file mode 100644 index 4f2c7b2..0000000 --- a/target/linux/mediatek/patches-4.9/0042-net-next-mediatek-honour-special-tag-bit-inside-RX-D.patch +++ /dev/null @@ -1,50 +0,0 @@ -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 deleted file mode 100644 index 2256325..0000000 --- a/target/linux/mediatek/patches-4.9/0043-net-next-mediatek-enable-special-tag-indication-for-.patch +++ /dev/null @@ -1,41 +0,0 @@ -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 deleted file mode 100644 index 51204d4..0000000 --- a/target/linux/mediatek/patches-4.9/0044-net-next-dsa-mediatek-tell-GDMA-when-we-are-turning-.patch +++ /dev/null @@ -1,43 +0,0 @@ -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 deleted file mode 100644 index c263b07..0000000 --- a/target/linux/mediatek/patches-4.9/0045-net-dsa-mediatek-turn-into-platform-driver.patch +++ /dev/null @@ -1,79 +0,0 @@ -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 deleted file mode 100644 index 47c3980..0000000 --- a/target/linux/mediatek/patches-4.9/0046-net-mediatek-add-irq-delay.patch +++ /dev/null @@ -1,56 +0,0 @@ -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 deleted file mode 100644 index 27a78a6..0000000 --- a/target/linux/mediatek/patches-4.9/0047-net-next-mediatek-split-IRQ-register-locking-into-TX.patch +++ /dev/null @@ -1,208 +0,0 @@ -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 deleted file mode 100644 index aeb81e1..0000000 --- a/target/linux/mediatek/patches-4.9/0048-net-core-add-RPS-balancer.patch +++ /dev/null @@ -1,90 +0,0 @@ -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 -@@ -3551,6 +3551,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. -@@ -3640,7 +3692,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; -@@ -8431,6 +8483,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 deleted file mode 100644 index 0146a9d..0000000 --- a/target/linux/mediatek/patches-4.9/0049-net-mediatek-add-rx-queue.patch +++ /dev/null @@ -1,20 +0,0 @@ -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 deleted file mode 100644 index 3d7df70..0000000 --- a/target/linux/mediatek/patches-4.9/0050-net-mediatek-add-trgmii-clock.patch +++ /dev/null @@ -1,21 +0,0 @@ -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 deleted file mode 100644 index 3de3e73..0000000 --- a/target/linux/mediatek/patches-4.9/0051-net-mediatek-increase-tx_timeout.patch +++ /dev/null @@ -1,21 +0,0 @@ -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 deleted file mode 100644 index 32d516c..0000000 --- a/target/linux/mediatek/patches-4.9/0052-net-phy-add-FC.patch +++ /dev/null @@ -1,21 +0,0 @@ -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 -@@ -1804,7 +1804,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 deleted file mode 100644 index a41bcb0..0000000 --- a/target/linux/mediatek/patches-4.9/0053-net-dsa-mediatek-add-software-phy-polling.patch +++ /dev/null @@ -1,68 +0,0 @@ -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 deleted file mode 100644 index 2900531..0000000 --- a/target/linux/mediatek/patches-4.9/0054-net-ethernet-mediatek-fixed-deadlock-captured-by-loc.patch +++ /dev/null @@ -1,105 +0,0 @@ -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 deleted file mode 100644 index 6598e82..0000000 --- a/target/linux/mediatek/patches-4.9/0055-net-ethernet-mediatek-avoid-potential-invalid-memory.patch +++ /dev/null @@ -1,31 +0,0 @@ -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 deleted file mode 100644 index d1d6ed4..0000000 --- a/target/linux/mediatek/patches-4.9/0056-net-mediatek-add-hw-nat-support.patch +++ /dev/null @@ -1,119 +0,0 @@ -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 deleted file mode 100644 index f628458..0000000 --- a/target/linux/mediatek/patches-4.9/0057-net-mediatek-add-HW-QoS-support.patch +++ /dev/null @@ -1,121 +0,0 @@ -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 deleted file mode 100644 index 3174b80..0000000 --- a/target/linux/mediatek/patches-4.9/0058-pinctrl-update.patch +++ /dev/null @@ -1,470 +0,0 @@ ---- 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 deleted file mode 100644 index c155961..0000000 --- a/target/linux/mediatek/patches-4.9/0059-eth-fixes.patch +++ /dev/null @@ -1,511 +0,0 @@ ---- 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; - ---- 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/0060-eth-debug.patch b/target/linux/mediatek/patches-4.9/0060-eth-debug.patch deleted file mode 100644 index 902a72e..0000000 --- a/target/linux/mediatek/patches-4.9/0060-eth-debug.patch +++ /dev/null @@ -1,69 +0,0 @@ ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -851,6 +851,7 @@ static void mtk_stop_queue(struct mtk_et - continue; - netif_stop_queue(eth->netdev[i]); - } -+ mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); - } - - static int mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) -@@ -1885,6 +1886,19 @@ static int mtk_start_dma(struct mtk_eth - return 0; - } - -+#define NAPI_TIMER_EXPIRE HZ -+ -+static void napi_timer_handler(unsigned long priv) -+{ -+ struct mtk_eth *eth = (struct mtk_eth*) priv; -+ -+ mtk_wake_queue(eth); -+ mtk_handle_irq_rx(0, eth); -+ mtk_handle_irq_tx(0, eth); -+ -+ mod_timer(ð->napi_timer, jiffies + NAPI_TIMER_EXPIRE); -+} -+ - static int mtk_open(struct net_device *dev) - { - struct mtk_mac *mac = netdev_priv(dev); -@@ -1901,6 +1915,9 @@ static int mtk_open(struct net_device *d - napi_enable(ð->rx_napi); - mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); - mtk_rx_irq_enable(eth, MTK_RX_DONE_INT); -+ -+ setup_timer(ð->napi_timer, napi_timer_handler, (unsigned long) eth); -+ mod_timer(ð->napi_timer, jiffies + NAPI_TIMER_EXPIRE); - } - atomic_inc(ð->dma_refcnt); - -@@ -1945,6 +1962,8 @@ static int mtk_stop(struct net_device *d - if (!atomic_dec_and_test(ð->dma_refcnt)) - return 0; - -+ del_timer(ð->napi_timer); -+ - mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); - mtk_rx_irq_disable(eth, MTK_RX_DONE_INT); - napi_disable(ð->tx_napi); -@@ -2524,7 +2543,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 = 15 * 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; - ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -601,6 +601,8 @@ struct mtk_eth { - struct mii_bus *mii_bus; - struct work_struct pending_work; - unsigned long state; -+ -+ struct timer_list napi_timer; - }; - - /* struct mtk_mac - the structure that holds the info about the MACs of the diff --git a/target/linux/mediatek/patches-4.9/0061-eth-up_down_lock.patch b/target/linux/mediatek/patches-4.9/0061-eth-up_down_lock.patch deleted file mode 100644 index e6f1cf6..0000000 --- a/target/linux/mediatek/patches-4.9/0061-eth-up_down_lock.patch +++ /dev/null @@ -1,72 +0,0 @@ ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1904,12 +1904,16 @@ static int mtk_open(struct net_device *d - struct mtk_mac *mac = netdev_priv(dev); - struct mtk_eth *eth = mac->hw; - -+ spin_lock(ð->iface_lock); -+ - /* we run 2 netdevs on the same dma ring so we only bring it up once */ - if (!atomic_read(ð->dma_refcnt)) { - int err = mtk_start_dma(eth); - -- if (err) -+ if (err) { -+ spin_unlock(ð->iface_lock); - return err; -+ } - - napi_enable(ð->tx_napi); - napi_enable(ð->rx_napi); -@@ -1923,6 +1927,7 @@ static int mtk_open(struct net_device *d - - phy_start(dev->phydev); - netif_start_queue(dev); -+ spin_unlock(ð->iface_lock); - - return 0; - } -@@ -1955,12 +1960,15 @@ static int mtk_stop(struct net_device *d - struct mtk_mac *mac = netdev_priv(dev); - struct mtk_eth *eth = mac->hw; - -+ spin_lock(ð->iface_lock); - netif_tx_disable(dev); - phy_stop(dev->phydev); - - /* only shutdown DMA if this is the last user */ -- if (!atomic_dec_and_test(ð->dma_refcnt)) -+ if (!atomic_dec_and_test(ð->dma_refcnt)) { -+ spin_unlock(ð->iface_lock); - return 0; -+ } - - del_timer(ð->napi_timer); - -@@ -1974,6 +1982,8 @@ static int mtk_stop(struct net_device *d - - mtk_dma_free(eth); - -+ spin_unlock(ð->iface_lock); -+ - return 0; - } - -@@ -2623,6 +2633,7 @@ static int mtk_probe(struct platform_dev - if (IS_ERR(eth->base)) - return PTR_ERR(eth->base); - -+ spin_lock_init(ð->iface_lock); - spin_lock_init(ð->page_lock); - spin_lock_init(ð->tx_irq_lock); - spin_lock_init(ð->rx_irq_lock); ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -573,6 +573,7 @@ struct mtk_rx_ring { - struct mtk_eth { - struct device *dev; - void __iomem *base; -+ spinlock_t iface_lock; - spinlock_t page_lock; - spinlock_t tx_irq_lock; - spinlock_t rx_irq_lock; diff --git a/target/linux/mediatek/patches-4.9/0062-mdio-atomic.patch b/target/linux/mediatek/patches-4.9/0062-mdio-atomic.patch deleted file mode 100644 index 96e7072..0000000 --- a/target/linux/mediatek/patches-4.9/0062-mdio-atomic.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -97,7 +97,10 @@ static int mtk_mdio_busy_wait(struct mtk - return 0; - if (time_after(jiffies, t_start + PHY_IAC_TIMEOUT)) - break; -- usleep_range(10, 20); -+ if (in_atomic()) -+ udelay(10); -+ else -+ usleep_range(10, 20); - } - - dev_err(eth->dev, "mdio: MDIO timeout\n"); diff --git a/target/linux/mediatek/patches-4.9/0063-atomic-sleep.patch b/target/linux/mediatek/patches-4.9/0063-atomic-sleep.patch deleted file mode 100644 index 095ce74..0000000 --- a/target/linux/mediatek/patches-4.9/0063-atomic-sleep.patch +++ /dev/null @@ -1,38 +0,0 @@ ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1533,7 +1533,10 @@ static void mtk_hwlro_rx_uninit(struct m - for (i = 0; i < 10; i++) { - val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0); - if (val & MTK_LRO_RING_RELINQUISH_DONE) { -- msleep(20); -+ if (in_atomic()) -+ mdelay(20); -+ else -+ msleep(20); - continue; - } - break; -@@ -1951,7 +1954,10 @@ static void mtk_stop_dma(struct mtk_eth - for (i = 0; i < 10; i++) { - val = mtk_r32(eth, glo_cfg); - if (val & (MTK_TX_DMA_BUSY | MTK_RX_DMA_BUSY)) { -- msleep(20); -+ if (in_atomic()) -+ mdelay(20); -+ else -+ msleep(20); - continue; - } - break; -@@ -1996,7 +2002,10 @@ static void ethsys_reset(struct mtk_eth - reset_bits, - reset_bits); - -- usleep_range(1000, 1100); -+ if (in_atomic()) -+ udelay(1000); -+ else -+ usleep_range(1000, 1100); - regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL, - reset_bits, - ~reset_bits); |