--- a/drivers/net/ethernet/mediatek/mt7530.c +++ b/drivers/net/ethernet/mediatek/mt7530.c @@ -44,6 +44,12 @@ #define MT7530_MAX_VID 4095 #define MT7530_MIN_VID 0 +#define MT7530_PORT_MIB_TXB_ID 2 /* TxGOC */ +#define MT7530_PORT_MIB_RXB_ID 6 /* RxGOC */ + +#define MT7621_PORT_MIB_TXB_ID 18 /* TxByte */ +#define MT7621_PORT_MIB_RXB_ID 37 /* RxByte */ + /* registers */ #define REG_ESW_VLAN_VTCR 0x90 #define REG_ESW_VLAN_VAWD1 0x94 @@ -214,6 +220,12 @@ struct mt7530_mapping { .members = { 0, 0x7e, 0x41 }, .etags = { 0, 0x40, 0x40 }, .vids = { 0, 1, 2 }, + }, { + .name = "lwlll", + .pvids = { 1, 2, 1, 1, 1, 1, 1 }, + .members = { 0, 0x7d, 0x42 }, + .etags = { 0, 0x40, 0x40 }, + .vids = { 0, 1, 2 }, }, }; @@ -467,6 +479,14 @@ mt7530_set_vid(struct switch_dev *dev, c } static int +mt7621_get_vid(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + val->value.i = val->port_vlan; + return 0; +} + +static int mt7530_get_vid(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) { @@ -485,6 +505,52 @@ mt7530_get_vid(struct switch_dev *dev, c return 0; } +static void +mt7530_write_vlan_entry(struct mt7530_priv *priv, int vlan, u16 vid, + u8 ports, u8 etags) +{ + int port; + u32 val; + +#ifndef CONFIG_SOC_MT7621 + /* vid of vlan */ + val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(vlan)); + if (vlan % 2 == 0) { + val &= 0xfff000; + val |= vid; + } else { + val &= 0xfff; + val |= (vid << 12); + } + mt7530_w32(priv, REG_ESW_VLAN_VTIM(vlan), val); +#endif + + /* vlan port membership */ + if (ports) + mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | + REG_ESW_VLAN_VAWD1_VTAG_EN | (ports << 16) | + REG_ESW_VLAN_VAWD1_VALID); + else + mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0); + + /* egress mode */ + val = 0; + for (port = 0; port < MT7530_NUM_PORTS; port++) { + if (etags & BIT(port)) + val |= ETAG_CTRL_TAG << (port * 2); + else + val |= ETAG_CTRL_UNTAG << (port * 2); + } + mt7530_w32(priv, REG_ESW_VLAN_VAWD2, val); + + /* write to vlan table */ +#ifdef CONFIG_SOC_MT7621 + mt7530_vtcr(priv, 1, vid); +#else + mt7530_vtcr(priv, 1, vlan); +#endif +} + static int mt7530_apply_config(struct switch_dev *dev) { @@ -541,51 +607,33 @@ mt7530_apply_config(struct switch_dev *d mt7530_w32(priv, REG_ESW_PORT_PVC(i), pvc_mode); } + /* first clear the swtich vlan table */ + for (i = 0; i < MT7530_NUM_VLANS; i++) + mt7530_write_vlan_entry(priv, i, i, 0, 0); + + /* now program only vlans with members to avoid + clobbering remapped entries in later iterations */ 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); + mt7530_write_vlan_entry(priv, i, vid, member, etags); } /* Port Default PVID */ for (i = 0; i < MT7530_NUM_PORTS; i++) { + int vlan = priv->port_entries[i].pvid; + u16 pvid = 0; u32 val; + + if (vlan < MT7530_NUM_VLANS && priv->vlan_entries[vlan].member) + pvid = priv->vlan_entries[vlan].vid; + val = mt7530_r32(priv, REG_ESW_PORT_PPBV1(i)); val &= ~0xfff; - val |= priv->port_entries[i].pvid; + val |= pvid; mt7530_w32(priv, REG_ESW_PORT_PPBV1(i), val); } @@ -739,6 +787,34 @@ static int mt7530_sw_get_port_mib(struct return 0; } +static int mt7530_get_port_stats(struct switch_dev *dev, int port, + struct switch_port_stats *stats) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + + if (port < 0 || port >= MT7530_NUM_PORTS) + return -EINVAL; + + stats->tx_bytes = get_mib_counter_port_7620(priv, MT7530_PORT_MIB_TXB_ID, port); + stats->rx_bytes = get_mib_counter_port_7620(priv, MT7530_PORT_MIB_RXB_ID, port); + + return 0; +} + +static int mt7621_get_port_stats(struct switch_dev *dev, int port, + struct switch_port_stats *stats) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + + if (port < 0 || port >= MT7530_NUM_PORTS) + return -EINVAL; + + stats->tx_bytes = get_mib_counter(priv, MT7621_PORT_MIB_TXB_ID, port); + stats->rx_bytes = get_mib_counter(priv, MT7621_PORT_MIB_RXB_ID, port); + + return 0; +} + static const struct switch_attr mt7530_global[] = { { .type = SWITCH_TYPE_INT, @@ -767,6 +843,17 @@ static const struct switch_attr mt7621_p }, }; +static const struct switch_attr mt7621_vlan[] = { + { + .type = SWITCH_TYPE_INT, + .name = "vid", + .description = "VLAN ID (0-4094)", + .set = mt7530_set_vid, + .get = mt7621_get_vid, + .max = 4094, + }, +}; + static const struct switch_attr mt7530_port[] = { { .type = SWITCH_TYPE_STRING, @@ -798,14 +885,15 @@ static const struct switch_dev_ops mt762 .n_attr = ARRAY_SIZE(mt7621_port), }, .attr_vlan = { - .attr = mt7530_vlan, - .n_attr = ARRAY_SIZE(mt7530_vlan), + .attr = mt7621_vlan, + .n_attr = ARRAY_SIZE(mt7621_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, + .get_port_stats = mt7621_get_port_stats, .apply_config = mt7530_apply_config, .reset_switch = mt7530_reset_switch, }; @@ -828,6 +916,7 @@ static const struct switch_dev_ops mt753 .get_port_pvid = mt7530_get_port_pvid, .set_port_pvid = mt7530_set_port_pvid, .get_port_link = mt7530_get_port_link, + .get_port_stats = mt7530_get_port_stats, .apply_config = mt7530_apply_config, .reset_switch = mt7530_reset_switch, }; @@ -881,7 +970,7 @@ mt7530_probe(struct device *dev, void __ /* 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"); + 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);