diff options
author | John Crispin <john@phrozen.org> | 2017-07-05 07:52:36 +0200 |
---|---|---|
committer | John Crispin <john@phrozen.org> | 2017-07-06 06:37:03 +0200 |
commit | fddc78bc116bc043fb5cd92dbc45cfd054c21af8 (patch) | |
tree | bb82a2b964986ddaec87414ab6b7b19b43ebc8b8 /target/linux/ramips/patches-4.4/0513-net-mediatek-add-swconfig-driver-for-gsw_mt762x.patch | |
parent | 05d6e92594c507dcd1f4be6c1bcb2282fe1abe1f (diff) | |
download | mtk-20170518-fddc78bc116bc043fb5cd92dbc45cfd054c21af8.zip mtk-20170518-fddc78bc116bc043fb5cd92dbc45cfd054c21af8.tar.gz mtk-20170518-fddc78bc116bc043fb5cd92dbc45cfd054c21af8.tar.bz2 |
ramips: bump to v4.9
Signed-off-by: John Crispin <john@phrozen.org>
Diffstat (limited to 'target/linux/ramips/patches-4.4/0513-net-mediatek-add-swconfig-driver-for-gsw_mt762x.patch')
-rw-r--r-- | target/linux/ramips/patches-4.4/0513-net-mediatek-add-swconfig-driver-for-gsw_mt762x.patch | 1181 |
1 files changed, 0 insertions, 1181 deletions
diff --git a/target/linux/ramips/patches-4.4/0513-net-mediatek-add-swconfig-driver-for-gsw_mt762x.patch b/target/linux/ramips/patches-4.4/0513-net-mediatek-add-swconfig-driver-for-gsw_mt762x.patch deleted file mode 100644 index 35d1bd0..0000000 --- a/target/linux/ramips/patches-4.4/0513-net-mediatek-add-swconfig-driver-for-gsw_mt762x.patch +++ /dev/null @@ -1,1181 +0,0 @@ -From cf5a08f1f16913da8bb24a96afaa2969b29d0827 Mon Sep 17 00:00:00 2001 -From: John Crispin <blogic@openwrt.org> -Date: Mon, 14 Dec 2015 22:25:57 +0100 -Subject: [PATCH 513/513] net: mediatek: add swconfig driver for gsw_mt762x - -Signed-off-by: John Crispin <blogic@openwrt.org> ---- - drivers/net/ethernet/mediatek/Makefile | 4 +- - drivers/net/ethernet/mediatek/gsw_mt7620.c | 3 + - drivers/net/ethernet/mediatek/gsw_mt7620.h | 3 + - drivers/net/ethernet/mediatek/mt7530.c | 884 ++++++++++++++++++++++++++++ - drivers/net/ethernet/mediatek/mt7530.h | 186 ++++++ - drivers/net/ethernet/mediatek/mtk_eth_soc.c | 9 +- - drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + - drivers/net/ethernet/mediatek/soc_mt7620.c | 1 + - 8 files changed, 1087 insertions(+), 4 deletions(-) - create mode 100644 drivers/net/ethernet/mediatek/mt7530.c - create mode 100644 drivers/net/ethernet/mediatek/mt7530.h - ---- a/drivers/net/ethernet/mediatek/Makefile -+++ b/drivers/net/ethernet/mediatek/Makefile -@@ -15,6 +15,6 @@ mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MT7620 - mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MT7621) += soc_mt7621.o - - obj-$(CONFIG_NET_MEDIATEK_ESW_RT3050) += esw_rt3050.o --obj-$(CONFIG_NET_MEDIATEK_GSW_MT7620) += gsw_mt7620.o --obj-$(CONFIG_NET_MEDIATEK_GSW_MT7621) += gsw_mt7621.o -+obj-$(CONFIG_NET_MEDIATEK_GSW_MT7620) += gsw_mt7620.o mt7530.o -+obj-$(CONFIG_NET_MEDIATEK_GSW_MT7621) += gsw_mt7621.o mt7530.o - obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk-eth-soc.o ---- a/drivers/net/ethernet/mediatek/gsw_mt7620.c -+++ b/drivers/net/ethernet/mediatek/gsw_mt7620.c -@@ -67,6 +67,9 @@ static void mt7620_hw_init(struct mt7620 - rt_sysc_w32(rt_sysc_r32(SYSC_REG_CFG1) | BIT(8), SYSC_REG_CFG1); - mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_CKGCR) & ~(0x3 << 4), GSW_REG_CKGCR); - -+ /* Enable MIB stats */ -+ mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_MIB_CNT_EN) | (1 << 1), GSW_REG_MIB_CNT_EN); -+ - if (of_property_read_bool(np, "mediatek,mt7530")) { - u32 val; - ---- a/drivers/net/ethernet/mediatek/gsw_mt7620.h -+++ b/drivers/net/ethernet/mediatek/gsw_mt7620.h -@@ -35,6 +35,8 @@ - #define GSW_MDIO_ADDR_SHIFT 20 - #define GSW_MDIO_REG_SHIFT 25 - -+#define GSW_REG_MIB_CNT_EN 0x4000 -+ - #define GSW_REG_PORT_PMCR(x) (0x3000 + (x * 0x100)) - #define GSW_REG_PORT_STATUS(x) (0x3008 + (x * 0x100)) - #define GSW_REG_SMACCR0 0x3fE4 -@@ -82,6 +84,7 @@ - #define PHY_PRE_EN BIT(30) - #define PMY_MDC_CONF(_x) ((_x & 0x3f) << 24) - -+ - enum { - /* Global attributes. */ - GSW_ATTR_ENABLE_VLAN, ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mt7530.c -@@ -0,0 +1,890 @@ -+/* -+ * 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. -+ * -+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> -+ * Copyright (C) 2016 Vitaly Chekryzhev <13hakta@gmail.com> -+ */ -+ -+#include <linux/if.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/list.h> -+#include <linux/if_ether.h> -+#include <linux/skbuff.h> -+#include <linux/netdevice.h> -+#include <linux/netlink.h> -+#include <linux/bitops.h> -+#include <net/genetlink.h> -+#include <linux/switch.h> -+#include <linux/delay.h> -+#include <linux/phy.h> -+#include <linux/netdevice.h> -+#include <linux/etherdevice.h> -+#include <linux/lockdep.h> -+#include <linux/workqueue.h> -+#include <linux/of_device.h> -+ -+#include "mt7530.h" -+ -+#define MT7530_CPU_PORT 6 -+#define MT7530_NUM_PORTS 8 -+#ifdef CONFIG_SOC_MT7621 -+#define MT7530_NUM_VLANS 4095 -+#else -+#define MT7530_NUM_VLANS 16 -+#endif -+#define MT7530_MAX_VID 4095 -+#define MT7530_MIN_VID 0 -+ -+/* registers */ -+#define REG_ESW_VLAN_VTCR 0x90 -+#define REG_ESW_VLAN_VAWD1 0x94 -+#define REG_ESW_VLAN_VAWD2 0x98 -+#define REG_ESW_VLAN_VTIM(x) (0x100 + 4 * ((x) / 2)) -+ -+#define REG_ESW_VLAN_VAWD1_IVL_MAC BIT(30) -+#define REG_ESW_VLAN_VAWD1_VTAG_EN BIT(28) -+#define REG_ESW_VLAN_VAWD1_VALID BIT(0) -+ -+/* vlan egress mode */ -+enum { -+ ETAG_CTRL_UNTAG = 0, -+ ETAG_CTRL_TAG = 2, -+ ETAG_CTRL_SWAP = 1, -+ ETAG_CTRL_STACK = 3, -+}; -+ -+#define REG_ESW_PORT_PCR(x) (0x2004 | ((x) << 8)) -+#define REG_ESW_PORT_PVC(x) (0x2010 | ((x) << 8)) -+#define REG_ESW_PORT_PPBV1(x) (0x2014 | ((x) << 8)) -+ -+#define REG_HWTRAP 0x7804 -+ -+#define MIB_DESC(_s , _o, _n) \ -+ { \ -+ .size = (_s), \ -+ .offset = (_o), \ -+ .name = (_n), \ -+ } -+ -+struct mt7xxx_mib_desc { -+ unsigned int size; -+ unsigned int offset; -+ const char *name; -+}; -+ -+static const struct mt7xxx_mib_desc mt7620_mibs[] = { -+ MIB_DESC(1, MT7620_MIB_STATS_PPE_AC_BCNT0, "PPE_AC_BCNT0"), -+ MIB_DESC(1, MT7620_MIB_STATS_PPE_AC_PCNT0, "PPE_AC_PCNT0"), -+ MIB_DESC(1, MT7620_MIB_STATS_PPE_AC_BCNT63, "PPE_AC_BCNT63"), -+ MIB_DESC(1, MT7620_MIB_STATS_PPE_AC_PCNT63, "PPE_AC_PCNT63"), -+ MIB_DESC(1, MT7620_MIB_STATS_PPE_MTR_CNT0, "PPE_MTR_CNT0"), -+ MIB_DESC(1, MT7620_MIB_STATS_PPE_MTR_CNT63, "PPE_MTR_CNT63"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM1_TX_GBCNT, "GDM1_TX_GBCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM1_TX_GPCNT, "GDM1_TX_GPCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM1_TX_SKIPCNT, "GDM1_TX_SKIPCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM1_TX_COLCNT, "GDM1_TX_COLCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_GBCNT1, "GDM1_RX_GBCNT1"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_GPCNT1, "GDM1_RX_GPCNT1"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_OERCNT, "GDM1_RX_OERCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_FERCNT, "GDM1_RX_FERCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_SERCNT, "GDM1_RX_SERCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_LERCNT, "GDM1_RX_LERCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_CERCNT, "GDM1_RX_CERCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_FCCNT, "GDM1_RX_FCCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM2_TX_GBCNT, "GDM2_TX_GBCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM2_TX_GPCNT, "GDM2_TX_GPCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM2_TX_SKIPCNT, "GDM2_TX_SKIPCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM2_TX_COLCNT, "GDM2_TX_COLCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_GBCNT, "GDM2_RX_GBCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_GPCNT, "GDM2_RX_GPCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_OERCNT, "GDM2_RX_OERCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_FERCNT, "GDM2_RX_FERCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_SERCNT, "GDM2_RX_SERCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_LERCNT, "GDM2_RX_LERCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_CERCNT, "GDM2_RX_CERCNT"), -+ MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_FCCNT, "GDM2_RX_FCCNT") -+}; -+ -+static const struct mt7xxx_mib_desc mt7620_port_mibs[] = { -+ MIB_DESC(1, MT7620_MIB_STATS_PORT_TGPCN, "TxGPC"), -+ MIB_DESC(1, MT7620_MIB_STATS_PORT_TBOCN, "TxBOC"), -+ MIB_DESC(1, MT7620_MIB_STATS_PORT_TGOCN, "TxGOC"), -+ MIB_DESC(1, MT7620_MIB_STATS_PORT_TEPCN, "TxEPC"), -+ MIB_DESC(1, MT7620_MIB_STATS_PORT_RGPCN, "RxGPC"), -+ MIB_DESC(1, MT7620_MIB_STATS_PORT_RBOCN, "RxBOC"), -+ MIB_DESC(1, MT7620_MIB_STATS_PORT_RGOCN, "RxGOC"), -+ MIB_DESC(1, MT7620_MIB_STATS_PORT_REPC1N, "RxEPC1"), -+ MIB_DESC(1, MT7620_MIB_STATS_PORT_REPC2N, "RxEPC2") -+}; -+ -+static const struct mt7xxx_mib_desc mt7621_mibs[] = { -+ MIB_DESC(1, MT7621_STATS_TDPC, "TxDrop"), -+ MIB_DESC(1, MT7621_STATS_TCRC, "TxCRC"), -+ MIB_DESC(1, MT7621_STATS_TUPC, "TxUni"), -+ MIB_DESC(1, MT7621_STATS_TMPC, "TxMulti"), -+ MIB_DESC(1, MT7621_STATS_TBPC, "TxBroad"), -+ MIB_DESC(1, MT7621_STATS_TCEC, "TxCollision"), -+ MIB_DESC(1, MT7621_STATS_TSCEC, "TxSingleCol"), -+ MIB_DESC(1, MT7621_STATS_TMCEC, "TxMultiCol"), -+ MIB_DESC(1, MT7621_STATS_TDEC, "TxDefer"), -+ MIB_DESC(1, MT7621_STATS_TLCEC, "TxLateCol"), -+ MIB_DESC(1, MT7621_STATS_TXCEC, "TxExcCol"), -+ MIB_DESC(1, MT7621_STATS_TPPC, "TxPause"), -+ MIB_DESC(1, MT7621_STATS_TL64PC, "Tx64Byte"), -+ MIB_DESC(1, MT7621_STATS_TL65PC, "Tx65Byte"), -+ MIB_DESC(1, MT7621_STATS_TL128PC, "Tx128Byte"), -+ MIB_DESC(1, MT7621_STATS_TL256PC, "Tx256Byte"), -+ MIB_DESC(1, MT7621_STATS_TL512PC, "Tx512Byte"), -+ MIB_DESC(1, MT7621_STATS_TL1024PC, "Tx1024Byte"), -+ MIB_DESC(2, MT7621_STATS_TOC, "TxByte"), -+ MIB_DESC(1, MT7621_STATS_RDPC, "RxDrop"), -+ MIB_DESC(1, MT7621_STATS_RFPC, "RxFiltered"), -+ MIB_DESC(1, MT7621_STATS_RUPC, "RxUni"), -+ MIB_DESC(1, MT7621_STATS_RMPC, "RxMulti"), -+ MIB_DESC(1, MT7621_STATS_RBPC, "RxBroad"), -+ MIB_DESC(1, MT7621_STATS_RAEPC, "RxAlignErr"), -+ MIB_DESC(1, MT7621_STATS_RCEPC, "RxCRC"), -+ MIB_DESC(1, MT7621_STATS_RUSPC, "RxUnderSize"), -+ MIB_DESC(1, MT7621_STATS_RFEPC, "RxFragment"), -+ MIB_DESC(1, MT7621_STATS_ROSPC, "RxOverSize"), -+ MIB_DESC(1, MT7621_STATS_RJEPC, "RxJabber"), -+ MIB_DESC(1, MT7621_STATS_RPPC, "RxPause"), -+ MIB_DESC(1, MT7621_STATS_RL64PC, "Rx64Byte"), -+ MIB_DESC(1, MT7621_STATS_RL65PC, "Rx65Byte"), -+ MIB_DESC(1, MT7621_STATS_RL128PC, "Rx128Byte"), -+ MIB_DESC(1, MT7621_STATS_RL256PC, "Rx256Byte"), -+ MIB_DESC(1, MT7621_STATS_RL512PC, "Rx512Byte"), -+ MIB_DESC(1, MT7621_STATS_RL1024PC, "Rx1024Byte"), -+ MIB_DESC(2, MT7621_STATS_ROC, "RxByte"), -+ MIB_DESC(1, MT7621_STATS_RDPC_CTRL, "RxCtrlDrop"), -+ MIB_DESC(1, MT7621_STATS_RDPC_ING, "RxIngDrop"), -+ MIB_DESC(1, MT7621_STATS_RDPC_ARL, "RxARLDrop") -+}; -+ -+enum { -+ /* Global attributes. */ -+ MT7530_ATTR_ENABLE_VLAN, -+}; -+ -+struct mt7530_port_entry { -+ u16 pvid; -+}; -+ -+struct mt7530_vlan_entry { -+ u16 vid; -+ u8 member; -+ u8 etags; -+}; -+ -+struct mt7530_priv { -+ void __iomem *base; -+ struct mii_bus *bus; -+ struct switch_dev swdev; -+ -+ bool global_vlan_enable; -+ struct mt7530_vlan_entry vlan_entries[MT7530_NUM_VLANS]; -+ struct mt7530_port_entry port_entries[MT7530_NUM_PORTS]; -+}; -+ -+struct mt7530_mapping { -+ char *name; -+ u16 pvids[MT7530_NUM_PORTS]; -+ u8 members[MT7530_NUM_VLANS]; -+ u8 etags[MT7530_NUM_VLANS]; -+ u16 vids[MT7530_NUM_VLANS]; -+} mt7530_defaults[] = { -+ { -+ .name = "llllw", -+ .pvids = { 1, 1, 1, 1, 2, 1, 1 }, -+ .members = { 0, 0x6f, 0x50 }, -+ .etags = { 0, 0x40, 0x40 }, -+ .vids = { 0, 1, 2 }, -+ }, { -+ .name = "wllll", -+ .pvids = { 2, 1, 1, 1, 1, 1, 1 }, -+ .members = { 0, 0x7e, 0x41 }, -+ .etags = { 0, 0x40, 0x40 }, -+ .vids = { 0, 1, 2 }, -+ }, -+}; -+ -+struct mt7530_mapping* -+mt7530_find_mapping(struct device_node *np) -+{ -+ const char *map; -+ int i; -+ -+ if (of_property_read_string(np, "mediatek,portmap", &map)) -+ return NULL; -+ -+ for (i = 0; i < ARRAY_SIZE(mt7530_defaults); i++) -+ if (!strcmp(map, mt7530_defaults[i].name)) -+ return &mt7530_defaults[i]; -+ -+ return NULL; -+} -+ -+static void -+mt7530_apply_mapping(struct mt7530_priv *mt7530, struct mt7530_mapping *map) -+{ -+ int i = 0; -+ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) -+ mt7530->port_entries[i].pvid = map->pvids[i]; -+ -+ for (i = 0; i < MT7530_NUM_VLANS; i++) { -+ mt7530->vlan_entries[i].member = map->members[i]; -+ mt7530->vlan_entries[i].etags = map->etags[i]; -+ mt7530->vlan_entries[i].vid = map->vids[i]; -+ } -+} -+ -+static int -+mt7530_reset_switch(struct switch_dev *dev) -+{ -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ int i; -+ -+ memset(priv->port_entries, 0, sizeof(priv->port_entries)); -+ memset(priv->vlan_entries, 0, sizeof(priv->vlan_entries)); -+ -+ /* set default vid of each vlan to the same number of vlan, so the vid -+ * won't need be set explicitly. -+ */ -+ for (i = 0; i < MT7530_NUM_VLANS; i++) { -+ priv->vlan_entries[i].vid = i; -+ } -+ -+ return 0; -+} -+ -+static int -+mt7530_get_vlan_enable(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ -+ val->value.i = priv->global_vlan_enable; -+ -+ return 0; -+} -+ -+static int -+mt7530_set_vlan_enable(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ -+ priv->global_vlan_enable = val->value.i != 0; -+ -+ return 0; -+} -+ -+static u32 -+mt7530_r32(struct mt7530_priv *priv, u32 reg) -+{ -+ u32 val; -+ if (priv->bus) { -+ u16 high, low; -+ -+ mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); -+ low = mdiobus_read(priv->bus, 0x1f, (reg >> 2) & 0xf); -+ high = mdiobus_read(priv->bus, 0x1f, 0x10); -+ -+ return (high << 16) | (low & 0xffff); -+ } -+ -+ val = ioread32(priv->base + reg); -+ pr_debug("MT7530 MDIO Read [%04x]=%08x\n", reg, val); -+ -+ return val; -+} -+ -+static void -+mt7530_w32(struct mt7530_priv *priv, u32 reg, u32 val) -+{ -+ if (priv->bus) { -+ mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); -+ mdiobus_write(priv->bus, 0x1f, (reg >> 2) & 0xf, val & 0xffff); -+ mdiobus_write(priv->bus, 0x1f, 0x10, val >> 16); -+ return; -+ } -+ -+ pr_debug("MT7530 MDIO Write[%04x]=%08x\n", reg, val); -+ iowrite32(val, priv->base + reg); -+} -+ -+static void -+mt7530_vtcr(struct mt7530_priv *priv, u32 cmd, u32 val) -+{ -+ int i; -+ -+ mt7530_w32(priv, REG_ESW_VLAN_VTCR, BIT(31) | (cmd << 12) | val); -+ -+ for (i = 0; i < 20; i++) { -+ u32 val = mt7530_r32(priv, REG_ESW_VLAN_VTCR); -+ -+ if ((val & BIT(31)) == 0) -+ break; -+ -+ udelay(1000); -+ } -+ if (i == 20) -+ printk("mt7530: vtcr timeout\n"); -+} -+ -+static int -+mt7530_get_port_pvid(struct switch_dev *dev, int port, int *val) -+{ -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ -+ if (port >= MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ *val = mt7530_r32(priv, REG_ESW_PORT_PPBV1(port)); -+ *val &= 0xfff; -+ -+ return 0; -+} -+ -+static int -+mt7530_set_port_pvid(struct switch_dev *dev, int port, int pvid) -+{ -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ -+ if (port >= MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ if (pvid < MT7530_MIN_VID || pvid > MT7530_MAX_VID) -+ return -EINVAL; -+ -+ priv->port_entries[port].pvid = pvid; -+ -+ return 0; -+} -+ -+static int -+mt7530_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) -+{ -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ u32 member; -+ u32 etags; -+ int i; -+ -+ val->len = 0; -+ -+ if (val->port_vlan < 0 || val->port_vlan >= MT7530_NUM_VLANS) -+ return -EINVAL; -+ -+ mt7530_vtcr(priv, 0, val->port_vlan); -+ -+ member = mt7530_r32(priv, REG_ESW_VLAN_VAWD1); -+ member >>= 16; -+ member &= 0xff; -+ -+ etags = mt7530_r32(priv, REG_ESW_VLAN_VAWD2); -+ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) { -+ struct switch_port *p; -+ int etag; -+ -+ if (!(member & BIT(i))) -+ continue; -+ -+ p = &val->value.ports[val->len++]; -+ p->id = i; -+ -+ etag = (etags >> (i * 2)) & 0x3; -+ -+ if (etag == ETAG_CTRL_TAG) -+ p->flags |= BIT(SWITCH_PORT_FLAG_TAGGED); -+ else if (etag != ETAG_CTRL_UNTAG) -+ printk("vlan egress tag control neither untag nor tag.\n"); -+ } -+ -+ return 0; -+} -+ -+static int -+mt7530_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) -+{ -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ u8 member = 0; -+ u8 etags = 0; -+ int i; -+ -+ if (val->port_vlan < 0 || val->port_vlan >= MT7530_NUM_VLANS || -+ val->len > MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ for (i = 0; i < val->len; i++) { -+ struct switch_port *p = &val->value.ports[i]; -+ -+ if (p->id >= MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ member |= BIT(p->id); -+ -+ if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) -+ etags |= BIT(p->id); -+ } -+ priv->vlan_entries[val->port_vlan].member = member; -+ priv->vlan_entries[val->port_vlan].etags = etags; -+ -+ return 0; -+} -+ -+static int -+mt7530_set_vid(struct switch_dev *dev, const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ int vlan; -+ u16 vid; -+ -+ vlan = val->port_vlan; -+ vid = (u16)val->value.i; -+ -+ if (vlan < 0 || vlan >= MT7530_NUM_VLANS) -+ return -EINVAL; -+ -+ if (vid < MT7530_MIN_VID || vid > MT7530_MAX_VID) -+ return -EINVAL; -+ -+ priv->vlan_entries[vlan].vid = vid; -+ return 0; -+} -+ -+static int -+mt7530_get_vid(struct switch_dev *dev, const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ u32 vid; -+ int vlan; -+ -+ vlan = val->port_vlan; -+ -+ vid = mt7530_r32(priv, REG_ESW_VLAN_VTIM(vlan)); -+ if (vlan & 1) -+ vid = vid >> 12; -+ vid &= 0xfff; -+ -+ val->value.i = vid; -+ return 0; -+} -+ -+static int -+mt7530_apply_config(struct switch_dev *dev) -+{ -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ int i, j; -+ u8 tag_ports; -+ u8 untag_ports; -+ -+ if (!priv->global_vlan_enable) { -+ for (i = 0; i < MT7530_NUM_PORTS; i++) -+ mt7530_w32(priv, REG_ESW_PORT_PCR(i), 0x00400000); -+ -+ mt7530_w32(priv, REG_ESW_PORT_PCR(MT7530_CPU_PORT), 0x00ff0000); -+ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) -+ mt7530_w32(priv, REG_ESW_PORT_PVC(i), 0x810000c0); -+ -+ return 0; -+ } -+ -+ /* set all ports as security mode */ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) -+ mt7530_w32(priv, REG_ESW_PORT_PCR(i), 0x00ff0003); -+ -+ /* check if a port is used in tag/untag vlan egress mode */ -+ tag_ports = 0; -+ untag_ports = 0; -+ -+ for (i = 0; i < MT7530_NUM_VLANS; i++) { -+ u8 member = priv->vlan_entries[i].member; -+ u8 etags = priv->vlan_entries[i].etags; -+ -+ if (!member) -+ continue; -+ -+ for (j = 0; j < MT7530_NUM_PORTS; j++) { -+ if (!(member & BIT(j))) -+ continue; -+ -+ if (etags & BIT(j)) -+ tag_ports |= 1u << j; -+ else -+ untag_ports |= 1u << j; -+ } -+ } -+ -+ /* set all untag-only ports as transparent and the rest as user port */ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) { -+ u32 pvc_mode = 0x81000000; -+ -+ if (untag_ports & BIT(i) && !(tag_ports & BIT(i))) -+ pvc_mode = 0x810000c0; -+ -+ mt7530_w32(priv, REG_ESW_PORT_PVC(i), pvc_mode); -+ } -+ -+ for (i = 0; i < MT7530_NUM_VLANS; i++) { -+ u16 vid = priv->vlan_entries[i].vid; -+ u8 member = priv->vlan_entries[i].member; -+ u8 etags = priv->vlan_entries[i].etags; -+ u32 val; -+ -+ /* vid of vlan */ -+ val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(i)); -+ if (i % 2 == 0) { -+ val &= 0xfff000; -+ val |= vid; -+ } else { -+ val &= 0xfff; -+ val |= (vid << 12); -+ } -+ mt7530_w32(priv, REG_ESW_VLAN_VTIM(i), val); -+ -+ /* vlan port membership */ -+ if (member) -+ mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | -+ REG_ESW_VLAN_VAWD1_VTAG_EN | (member << 16) | -+ REG_ESW_VLAN_VAWD1_VALID); -+ else -+ mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0); -+ -+ /* egress mode */ -+ val = 0; -+ for (j = 0; j < MT7530_NUM_PORTS; j++) { -+ if (etags & BIT(j)) -+ val |= ETAG_CTRL_TAG << (j * 2); -+ else -+ val |= ETAG_CTRL_UNTAG << (j * 2); -+ } -+ mt7530_w32(priv, REG_ESW_VLAN_VAWD2, val); -+ -+ /* write to vlan table */ -+ mt7530_vtcr(priv, 1, i); -+ } -+ -+ /* Port Default PVID */ -+ for (i = 0; i < MT7530_NUM_PORTS; i++) { -+ u32 val; -+ val = mt7530_r32(priv, REG_ESW_PORT_PPBV1(i)); -+ val &= ~0xfff; -+ val |= priv->port_entries[i].pvid; -+ mt7530_w32(priv, REG_ESW_PORT_PPBV1(i), val); -+ } -+ -+ return 0; -+} -+ -+static int -+mt7530_get_port_link(struct switch_dev *dev, int port, -+ struct switch_port_link *link) -+{ -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ u32 speed, pmsr; -+ -+ if (port < 0 || port >= MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ pmsr = mt7530_r32(priv, 0x3008 + (0x100 * port)); -+ -+ link->link = pmsr & 1; -+ link->duplex = (pmsr >> 1) & 1; -+ speed = (pmsr >> 2) & 3; -+ -+ switch (speed) { -+ case 0: -+ link->speed = SWITCH_PORT_SPEED_10; -+ break; -+ case 1: -+ link->speed = SWITCH_PORT_SPEED_100; -+ break; -+ case 2: -+ case 3: /* forced gige speed can be 2 or 3 */ -+ link->speed = SWITCH_PORT_SPEED_1000; -+ break; -+ default: -+ link->speed = SWITCH_PORT_SPEED_UNKNOWN; -+ break; -+ } -+ -+ return 0; -+} -+ -+static u64 get_mib_counter(struct mt7530_priv *priv, int i, int port) -+{ -+ unsigned int port_base; -+ u64 lo; -+ -+ port_base = MT7621_MIB_COUNTER_BASE + -+ MT7621_MIB_COUNTER_PORT_OFFSET * port; -+ -+ lo = mt7530_r32(priv, port_base + mt7621_mibs[i].offset); -+ if (mt7621_mibs[i].size == 2) { -+ u64 hi; -+ -+ hi = mt7530_r32(priv, port_base + mt7621_mibs[i].offset + 4); -+ lo |= hi << 32; -+ } -+ -+ return lo; -+} -+ -+static int mt7621_sw_get_port_mib(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ static char buf[4096]; -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ int i, len = 0; -+ -+ if (val->port_vlan >= MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ len += snprintf(buf + len, sizeof(buf) - len, -+ "Port %d MIB counters\n", val->port_vlan); -+ -+ for (i = 0; i < ARRAY_SIZE(mt7621_mibs); ++i) { -+ u64 counter; -+ len += snprintf(buf + len, sizeof(buf) - len, -+ "%-11s: ", mt7621_mibs[i].name); -+ counter = get_mib_counter(priv, i, val->port_vlan); -+ len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", -+ counter); -+ } -+ -+ val->value.s = buf; -+ val->len = len; -+ return 0; -+} -+ -+static u64 get_mib_counter_7620(struct mt7530_priv *priv, int i) -+{ -+ return mt7530_r32(priv, MT7620_MIB_COUNTER_BASE + mt7620_mibs[i].offset); -+} -+ -+static u64 get_mib_counter_port_7620(struct mt7530_priv *priv, int i, int port) -+{ -+ return mt7530_r32(priv, -+ MT7620_MIB_COUNTER_BASE_PORT + -+ (MT7620_MIB_COUNTER_PORT_OFFSET * port) + -+ mt7620_port_mibs[i].offset); -+} -+ -+static int mt7530_sw_get_mib(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ static char buf[4096]; -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ int i, len = 0; -+ -+ len += snprintf(buf + len, sizeof(buf) - len, "Switch MIB counters\n"); -+ -+ for (i = 0; i < ARRAY_SIZE(mt7620_mibs); ++i) { -+ u64 counter; -+ len += snprintf(buf + len, sizeof(buf) - len, -+ "%-11s: ", mt7620_mibs[i].name); -+ counter = get_mib_counter_7620(priv, i); -+ len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", -+ counter); -+ } -+ -+ val->value.s = buf; -+ val->len = len; -+ return 0; -+} -+ -+static int mt7530_sw_get_port_mib(struct switch_dev *dev, -+ const struct switch_attr *attr, -+ struct switch_val *val) -+{ -+ static char buf[4096]; -+ struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); -+ int i, len = 0; -+ -+ if (val->port_vlan >= MT7530_NUM_PORTS) -+ return -EINVAL; -+ -+ len += snprintf(buf + len, sizeof(buf) - len, -+ "Port %d MIB counters\n", val->port_vlan); -+ -+ for (i = 0; i < ARRAY_SIZE(mt7620_port_mibs); ++i) { -+ u64 counter; -+ len += snprintf(buf + len, sizeof(buf) - len, -+ "%-11s: ", mt7620_port_mibs[i].name); -+ counter = get_mib_counter_port_7620(priv, i, val->port_vlan); -+ len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", -+ counter); -+ } -+ -+ val->value.s = buf; -+ val->len = len; -+ return 0; -+} -+ -+static const struct switch_attr mt7530_global[] = { -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "enable_vlan", -+ .description = "VLAN mode (1:enabled)", -+ .max = 1, -+ .id = MT7530_ATTR_ENABLE_VLAN, -+ .get = mt7530_get_vlan_enable, -+ .set = mt7530_set_vlan_enable, -+ }, { -+ .type = SWITCH_TYPE_STRING, -+ .name = "mib", -+ .description = "Get MIB counters for switch", -+ .get = mt7530_sw_get_mib, -+ .set = NULL, -+ }, -+}; -+ -+static const struct switch_attr mt7621_port[] = { -+ { -+ .type = SWITCH_TYPE_STRING, -+ .name = "mib", -+ .description = "Get MIB counters for port", -+ .get = mt7621_sw_get_port_mib, -+ .set = NULL, -+ }, -+}; -+ -+static const struct switch_attr mt7530_port[] = { -+ { -+ .type = SWITCH_TYPE_STRING, -+ .name = "mib", -+ .description = "Get MIB counters for port", -+ .get = mt7530_sw_get_port_mib, -+ .set = NULL, -+ }, -+}; -+ -+static const struct switch_attr mt7530_vlan[] = { -+ { -+ .type = SWITCH_TYPE_INT, -+ .name = "vid", -+ .description = "VLAN ID (0-4094)", -+ .set = mt7530_set_vid, -+ .get = mt7530_get_vid, -+ .max = 4094, -+ }, -+}; -+ -+static const struct switch_dev_ops mt7621_ops = { -+ .attr_global = { -+ .attr = mt7530_global, -+ .n_attr = ARRAY_SIZE(mt7530_global), -+ }, -+ .attr_port = { -+ .attr = mt7621_port, -+ .n_attr = ARRAY_SIZE(mt7621_port), -+ }, -+ .attr_vlan = { -+ .attr = mt7530_vlan, -+ .n_attr = ARRAY_SIZE(mt7530_vlan), -+ }, -+ .get_vlan_ports = mt7530_get_vlan_ports, -+ .set_vlan_ports = mt7530_set_vlan_ports, -+ .get_port_pvid = mt7530_get_port_pvid, -+ .set_port_pvid = mt7530_set_port_pvid, -+ .get_port_link = mt7530_get_port_link, -+ .apply_config = mt7530_apply_config, -+ .reset_switch = mt7530_reset_switch, -+}; -+ -+static const struct switch_dev_ops mt7530_ops = { -+ .attr_global = { -+ .attr = mt7530_global, -+ .n_attr = ARRAY_SIZE(mt7530_global), -+ }, -+ .attr_port = { -+ .attr = mt7530_port, -+ .n_attr = ARRAY_SIZE(mt7530_port), -+ }, -+ .attr_vlan = { -+ .attr = mt7530_vlan, -+ .n_attr = ARRAY_SIZE(mt7530_vlan), -+ }, -+ .get_vlan_ports = mt7530_get_vlan_ports, -+ .set_vlan_ports = mt7530_set_vlan_ports, -+ .get_port_pvid = mt7530_get_port_pvid, -+ .set_port_pvid = mt7530_set_port_pvid, -+ .get_port_link = mt7530_get_port_link, -+ .apply_config = mt7530_apply_config, -+ .reset_switch = mt7530_reset_switch, -+}; -+ -+int -+mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vlan) -+{ -+ struct switch_dev *swdev; -+ struct mt7530_priv *mt7530; -+ struct mt7530_mapping *map; -+ int ret; -+ -+ mt7530 = devm_kzalloc(dev, sizeof(struct mt7530_priv), GFP_KERNEL); -+ if (!mt7530) -+ return -ENOMEM; -+ -+ mt7530->base = base; -+ mt7530->bus = bus; -+ mt7530->global_vlan_enable = vlan; -+ -+ swdev = &mt7530->swdev; -+ if (bus) { -+ swdev->alias = "mt7530"; -+ swdev->name = "mt7530"; -+ } else if (IS_ENABLED(CONFIG_SOC_MT7621)) { -+ swdev->alias = "mt7621"; -+ swdev->name = "mt7621"; -+ } else { -+ swdev->alias = "mt7620"; -+ swdev->name = "mt7620"; -+ } -+ swdev->cpu_port = MT7530_CPU_PORT; -+ swdev->ports = MT7530_NUM_PORTS; -+ swdev->vlans = MT7530_NUM_VLANS; -+ if (IS_ENABLED(CONFIG_SOC_MT7621)) -+ swdev->ops = &mt7621_ops; -+ else -+ swdev->ops = &mt7530_ops; -+ -+ ret = register_switch(swdev, NULL); -+ if (ret) { -+ dev_err(dev, "failed to register mt7530\n"); -+ return ret; -+ } -+ -+ -+ map = mt7530_find_mapping(dev->of_node); -+ if (map) -+ mt7530_apply_mapping(mt7530, map); -+ mt7530_apply_config(swdev); -+ -+ /* magic vodoo */ -+ if (!IS_ENABLED(CONFIG_SOC_MT7621) && bus && mt7530_r32(mt7530, REG_HWTRAP) != 0x1117edf) { -+ dev_info(dev, "fixing up MHWTRAP register - bootloader probably played with it\n"); -+ mt7530_w32(mt7530, REG_HWTRAP, 0x1117edf); -+ } -+ dev_info(dev, "loaded %s driver\n", swdev->name); -+ -+ return 0; -+} ---- /dev/null -+++ b/drivers/net/ethernet/mediatek/mt7530.h -@@ -0,0 +1,186 @@ -+/* -+ * 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. -+ * -+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> -+ * Copyright (C) 2016 Vitaly Chekryzhev <13hakta@gmail.com> -+ */ -+ -+#ifndef _MT7530_H__ -+#define _MT7530_H__ -+ -+#define MT7620_MIB_COUNTER_BASE_PORT 0x4000 -+#define MT7620_MIB_COUNTER_PORT_OFFSET 0x100 -+#define MT7620_MIB_COUNTER_BASE 0x1010 -+ -+/* PPE Accounting Group #0 Byte Counter */ -+#define MT7620_MIB_STATS_PPE_AC_BCNT0 0x000 -+ -+/* PPE Accounting Group #0 Packet Counter */ -+#define MT7620_MIB_STATS_PPE_AC_PCNT0 0x004 -+ -+/* PPE Accounting Group #63 Byte Counter */ -+#define MT7620_MIB_STATS_PPE_AC_BCNT63 0x1F8 -+ -+/* PPE Accounting Group #63 Packet Counter */ -+#define MT7620_MIB_STATS_PPE_AC_PCNT63 0x1FC -+ -+/* PPE Meter Group #0 */ -+#define MT7620_MIB_STATS_PPE_MTR_CNT0 0x200 -+ -+/* PPE Meter Group #63 */ -+#define MT7620_MIB_STATS_PPE_MTR_CNT63 0x2FC -+ -+/* Transmit good byte count for CPU GDM */ -+#define MT7620_MIB_STATS_GDM1_TX_GBCNT 0x300 -+ -+/* Transmit good packet count for CPU GDM (exclude flow control frames) */ -+#define MT7620_MIB_STATS_GDM1_TX_GPCNT 0x304 -+ -+/* Transmit abort count for CPU GDM */ -+#define MT7620_MIB_STATS_GDM1_TX_SKIPCNT 0x308 -+ -+/* Transmit collision count for CPU GDM */ -+#define MT7620_MIB_STATS_GDM1_TX_COLCNT 0x30C -+ -+/* Received good byte count for CPU GDM */ -+#define MT7620_MIB_STATS_GDM1_RX_GBCNT1 0x320 -+ -+/* Received good packet count for CPU GDM (exclude flow control frame) */ -+#define MT7620_MIB_STATS_GDM1_RX_GPCNT1 0x324 -+ -+/* Received overflow error packet count for CPU GDM */ -+#define MT7620_MIB_STATS_GDM1_RX_OERCNT 0x328 -+ -+/* Received FCS error packet count for CPU GDM */ -+#define MT7620_MIB_STATS_GDM1_RX_FERCNT 0x32C -+ -+/* Received too short error packet count for CPU GDM */ -+#define MT7620_MIB_STATS_GDM1_RX_SERCNT 0x330 -+ -+/* Received too long error packet count for CPU GDM */ -+#define MT7620_MIB_STATS_GDM1_RX_LERCNT 0x334 -+ -+/* Received IP/TCP/UDP checksum error packet count for CPU GDM */ -+#define MT7620_MIB_STATS_GDM1_RX_CERCNT 0x338 -+ -+/* Received flow control pkt count for CPU GDM */ -+#define MT7620_MIB_STATS_GDM1_RX_FCCNT 0x33C -+ -+/* Transmit good byte count for PPE GDM */ -+#define MT7620_MIB_STATS_GDM2_TX_GBCNT 0x340 -+ -+/* Transmit good packet count for PPE GDM (exclude flow control frames) */ -+#define MT7620_MIB_STATS_GDM2_TX_GPCNT 0x344 -+ -+/* Transmit abort count for PPE GDM */ -+#define MT7620_MIB_STATS_GDM2_TX_SKIPCNT 0x348 -+ -+/* Transmit collision count for PPE GDM */ -+#define MT7620_MIB_STATS_GDM2_TX_COLCNT 0x34C -+ -+/* Received good byte count for PPE GDM */ -+#define MT7620_MIB_STATS_GDM2_RX_GBCNT 0x360 -+ -+/* Received good packet count for PPE GDM (exclude flow control frame) */ -+#define MT7620_MIB_STATS_GDM2_RX_GPCNT 0x364 -+ -+/* Received overflow error packet count for PPE GDM */ -+#define MT7620_MIB_STATS_GDM2_RX_OERCNT 0x368 -+ -+/* Received FCS error packet count for PPE GDM */ -+#define MT7620_MIB_STATS_GDM2_RX_FERCNT 0x36C -+ -+/* Received too short error packet count for PPE GDM */ -+#define MT7620_MIB_STATS_GDM2_RX_SERCNT 0x370 -+ -+/* Received too long error packet count for PPE GDM */ -+#define MT7620_MIB_STATS_GDM2_RX_LERCNT 0x374 -+ -+/* Received IP/TCP/UDP checksum error packet count for PPE GDM */ -+#define MT7620_MIB_STATS_GDM2_RX_CERCNT 0x378 -+ -+/* Received flow control pkt count for PPE GDM */ -+#define MT7620_MIB_STATS_GDM2_RX_FCCNT 0x37C -+ -+/* Tx Packet Counter of Port n */ -+#define MT7620_MIB_STATS_PORT_TGPCN 0x10 -+ -+/* Tx Bad Octet Counter of Port n */ -+#define MT7620_MIB_STATS_PORT_TBOCN 0x14 -+ -+/* Tx Good Octet Counter of Port n */ -+#define MT7620_MIB_STATS_PORT_TGOCN 0x18 -+ -+/* Tx Event Packet Counter of Port n */ -+#define MT7620_MIB_STATS_PORT_TEPCN 0x1C -+ -+/* Rx Packet Counter of Port n */ -+#define MT7620_MIB_STATS_PORT_RGPCN 0x20 -+ -+/* Rx Bad Octet Counter of Port n */ -+#define MT7620_MIB_STATS_PORT_RBOCN 0x24 -+ -+/* Rx Good Octet Counter of Port n */ -+#define MT7620_MIB_STATS_PORT_RGOCN 0x28 -+ -+/* Rx Event Packet Counter of Port n */ -+#define MT7620_MIB_STATS_PORT_REPC1N 0x2C -+ -+/* Rx Event Packet Counter of Port n */ -+#define MT7620_MIB_STATS_PORT_REPC2N 0x30 -+ -+#define MT7621_MIB_COUNTER_BASE 0x4000 -+#define MT7621_MIB_COUNTER_PORT_OFFSET 0x100 -+#define MT7621_STATS_TDPC 0x00 -+#define MT7621_STATS_TCRC 0x04 -+#define MT7621_STATS_TUPC 0x08 -+#define MT7621_STATS_TMPC 0x0C -+#define MT7621_STATS_TBPC 0x10 -+#define MT7621_STATS_TCEC 0x14 -+#define MT7621_STATS_TSCEC 0x18 -+#define MT7621_STATS_TMCEC 0x1C -+#define MT7621_STATS_TDEC 0x20 -+#define MT7621_STATS_TLCEC 0x24 -+#define MT7621_STATS_TXCEC 0x28 -+#define MT7621_STATS_TPPC 0x2C -+#define MT7621_STATS_TL64PC 0x30 -+#define MT7621_STATS_TL65PC 0x34 -+#define MT7621_STATS_TL128PC 0x38 -+#define MT7621_STATS_TL256PC 0x3C -+#define MT7621_STATS_TL512PC 0x40 -+#define MT7621_STATS_TL1024PC 0x44 -+#define MT7621_STATS_TOC 0x48 -+#define MT7621_STATS_RDPC 0x60 -+#define MT7621_STATS_RFPC 0x64 -+#define MT7621_STATS_RUPC 0x68 -+#define MT7621_STATS_RMPC 0x6C -+#define MT7621_STATS_RBPC 0x70 -+#define MT7621_STATS_RAEPC 0x74 -+#define MT7621_STATS_RCEPC 0x78 -+#define MT7621_STATS_RUSPC 0x7C -+#define MT7621_STATS_RFEPC 0x80 -+#define MT7621_STATS_ROSPC 0x84 -+#define MT7621_STATS_RJEPC 0x88 -+#define MT7621_STATS_RPPC 0x8C -+#define MT7621_STATS_RL64PC 0x90 -+#define MT7621_STATS_RL65PC 0x94 -+#define MT7621_STATS_RL128PC 0x98 -+#define MT7621_STATS_RL256PC 0x9C -+#define MT7621_STATS_RL512PC 0xA0 -+#define MT7621_STATS_RL1024PC 0xA4 -+#define MT7621_STATS_ROC 0xA8 -+#define MT7621_STATS_RDPC_CTRL 0xB0 -+#define MT7621_STATS_RDPC_ING 0xB4 -+#define MT7621_STATS_RDPC_ARL 0xB8 -+ -+int mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vlan); -+ -+#endif ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -1291,8 +1291,13 @@ static int __init fe_init(struct net_dev - } - - err = fe_hw_init(dev); -- if (!err) -- return 0; -+ if (err) -+ goto err_phy_disconnect; -+ -+ if ((priv->flags & FE_FLAG_HAS_SWITCH) && priv->soc->switch_config) -+ priv->soc->switch_config(priv); -+ -+ return 0; - - err_phy_disconnect: - if (priv->phy) ---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h -+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -383,6 +383,7 @@ struct fe_soc_data { - int (*fwd_config)(struct fe_priv *priv); - void (*tx_dma)(struct fe_tx_dma *txd); - int (*switch_init)(struct fe_priv *priv); -+ int (*switch_config)(struct fe_priv *priv); - void (*port_init)(struct fe_priv *priv, struct device_node *port); - int (*has_carrier)(struct fe_priv *priv); - int (*mdio_init)(struct fe_priv *priv); ---- a/drivers/net/ethernet/mediatek/soc_mt7620.c -+++ b/drivers/net/ethernet/mediatek/soc_mt7620.c -@@ -313,6 +313,7 @@ static struct fe_soc_data mt7620_data = - .fwd_config = mt7620_fwd_config, - .tx_dma = mt7620_tx_dma, - .switch_init = mtk_gsw_init, -+ .switch_config = mt7620_gsw_config, - .port_init = mt7620_port_init, - .reg_table = mt7620_reg_table, - .pdma_glo_cfg = FE_PDMA_SIZE_16DWORDS, |