On 24/06/2014 15:54, Xiongfei(Alex) GUO wrote: > hi, > > I'm test it on Mercury MW305R with a modified dts file for > RT-N14U. Maybe I can give a dts patch for this board later. > > Actually, MT7530 is the ethernet switch inside the MTK MT7620A/N. > So you can try it with any MT7620 based board.
it is also the ip core inside the external chip and its inside the mt7621. that is why i ask, testing on mt7620 only is not enough we need to test a few more boards. DTS file patches are welcome ... thanks for the info i hope to look at this the next 2 days John > > Xiongfei Guo Credo Semi. > > > On Tue, Jun 24, 2014 at 8:54 PM, John Crispin <j...@phrozen.org > <mailto:j...@phrozen.org>> wrote: > > Hi, > > On 21/06/2014 17:10, xf...@credosemi.com > <mailto:xf...@credosemi.com> wrote: >> From: Xiongfei Guo <xf...@credosemi.com >> <mailto:xf...@credosemi.com>> >> >> - Support set VLAN ID of each vlan. - Support untag feature. - >> Replace register address with C MACRO. - There are 8 ports for >> MT7530 actually. >> >> Signed-off-by: Xiongfei Guo <xf...@credosemi.com > <mailto:xf...@credosemi.com>> > > > on which boards did you test this ? i want to give it a quick try > on the eval kit today before merging the patch. i have so far not > seen any boards in the wild with this switch > > John > >> --- ...8-NET-MIPS-add-ralink-SoC-ethernet-driver.patch | 268 >> ++++++++++++++------- 1 file changed, 186 insertions(+), 82 >> deletions(-) >> >> diff --git >> > a/target/linux/ramips/patches-3.10/0118-NET-MIPS-add-ralink-SoC-ethernet-driver.patch > > > > b/target/linux/ramips/patches-3.10/0118-NET-MIPS-add-ralink-SoC-ethernet-driver.patch > > > >> > index 75f78bf..c8ec17c 100644 >> --- >> > a/target/linux/ramips/patches-3.10/0118-NET-MIPS-add-ralink-SoC-ethernet-driver.patch > > > >> > +++ > b/target/linux/ramips/patches-3.10/0118-NET-MIPS-add-ralink-SoC-ethernet-driver.patch > > @@ -2814,7 +2814,7 @@ Signed-off-by: John Crispin >> <blo...@openwrt.org <mailto:blo...@openwrt.org>> +#endif --- > /dev/null +++ >> b/drivers/net/ethernet/ralink/mt7530.c -@@ -0,0 +1,467 @@ +@@ >> -0,0 +1,571 @@ +/* + * This program is free software; you can >> redistribute it and/or + * modify it under the terms of the GNU >> General Public License @@ -2851,25 +2851,45 @@ Signed-off-by: >> John Crispin <blo...@openwrt.org <mailto:blo...@openwrt.org>> >> +#include > "mt7530.h" + +#define >> MT7530_CPU_PORT 6 -+#define MT7530_NUM_PORTS 7 > ++#define >> MT7530_NUM_PORTS 8 +#define MT7530_NUM_VLANS 16 >> -+#define MT7530_NUM_VIDS 16 ++#define >> MT7530_MAX_VID > 4095 ++#define >> MT7530_MIN_VID 0 + -+#define REG_ESW_VLAN_VTCR >> 0x90 > -+#define >> REG_ESW_VLAN_VAWD1 0x94 -+#define REG_ESW_VLAN_VAWD2 >> 0x98 > ++/* >> 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)) +enum >> { + /* Global attributes. */ + MT7530_ATTR_ENABLE_VLAN, >> +}; + -+struct mt7530_port { ++struct mt7530_port_entry { + u16 >> pvid; +}; + -+struct mt7530_vlan { -+ u8 ports; >> ++struct mt7530_vlan_entry { ++ u16 vid; ++ u8 >> member; ++ > u8 etags; +}; + >> +struct mt7530_priv { @@ -2878,23 +2898,29 @@ Signed-off-by: >> John Crispin <blo...@openwrt.org <mailto:blo...@openwrt.org>> + >> > struct switch_dev swdev; + + bool >> global_vlan_enable; -+ struct mt7530_vlan > vlans[MT7530_NUM_VLANS]; >> -+ struct mt7530_port ports[MT7530_NUM_PORTS]; ++ >> struct mt7530_vlan_entry vlan_entries[MT7530_NUM_VLANS]; ++ >> struct mt7530_port_entry port_entries[MT7530_NUM_PORTS]; +}; >> + +struct mt7530_mapping { + char *name; -+ u8 >> pvids[6]; -+ > u8 vlans[8]; ++ >> 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 }, -+ .vlans = { 0, 0x6f, 0x50 }, ++ >> > .pvids = { 1, 1, >> 1, 1, 2, 1, 1 }, ++ .members = { 0x6f, 0x50 }, ++ >> > .etags = { >> 0x40, 0x40 }, ++ .vids = { 1, 2 }, + }, { + >> > .name = "wllll", -+ >> .pvids = { 2, 1, 1, 1, 1, 1 }, -+ .vlans = { 0, >> 0x7e, > 0x41 }, ++ >> .pvids = { 2, 1, 1, 1, 1, 1, 1 }, ++ .members = { 0x7e, > 0x41 }, ++ >> .etags = { 0x40, 0x40 }, ++ .vids = { 1, 2 }, + }, > +}; + @@ >> -2921,10 +2947,14 @@ Signed-off-by: John Crispin >> <blo...@openwrt.org <mailto:blo...@openwrt.org>> + + > mt7530->global_vlan_enable = 1; + -+ for >> (i = 0; i < 6; i++) -+ mt7530->ports[i].pvid = > map->pvids[i]; -+ >> for (i = 0; i < 8; i++) -+ mt7530->vlans[i].ports = >> map->vlans[i]; ++ 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 @@ -2932,8 +2962,8 @@ Signed-off-by: John >> Crispin <blo...@openwrt.org <mailto:blo...@openwrt.org>> +{ + >> > struct mt7530_priv *priv = >> container_of(dev, struct mt7530_priv, swdev); + -+ >> memset(priv->ports, 0, sizeof(priv->ports)); -+ > memset(priv->vlans, >> 0, sizeof(priv->vlans)); ++ memset(priv->port_entries, 0, >> sizeof(priv->port_entries)); ++ memset(priv->vlan_entries, >> 0, sizeof(priv->vlan_entries)); + + return 0; +} @@ -2965,6 > +2995,7 @@ >> Signed-off-by: John Crispin <blo...@openwrt.org > <mailto:blo...@openwrt.org>> +static u32 >> +mt7530_r32(struct mt7530_priv *priv, u32 reg) +{ ++ u32 val; + >> > if >> (priv->bus) { + u16 high, low; + @@ -2975,7 >> +3006,10 @@ Signed-off-by: John Crispin <blo...@openwrt.org > <mailto:blo...@openwrt.org>> + return (high << >> 16) | (low & 0xffff); + } + -+ return > ioread32(priv->base + >> reg); ++ val = ioread32(priv->base + reg); ++ > pr_debug("MT7530 MDIO >> Read [%04x]=%08x\n", reg, val); ++ ++ return val; +} + +static >> void @@ -2988,6 +3022,7 @@ Signed-off-by: John Crispin >> <blo...@openwrt.org <mailto:blo...@openwrt.org>> + > return; + } + ++ pr_debug("MT7530 MDIO >> Write[%04x]=%08x\n", reg, val); + iowrite32(val, priv->base >> + reg); +} + @@ -3018,8 +3053,8 @@ Signed-off-by: John Crispin >> <blo...@openwrt.org <mailto:blo...@openwrt.org>> + if >> (port = MT7530_NUM_PORTS) + return -EINVAL; + -+ *val = >> mt7530_r32(priv, 0x2014 + (0x100 * port)); -+ *val &= 0xff; ++ >> *val = mt7530_r32(priv, REG_ESW_PORT_PPBV1(port)); ++ *val &= >> 0xfff; + + return 0; +} @@ -3030,9 +3065,12 @@ >> Signed-off-by: John Crispin <blo...@openwrt.org >> <mailto:blo...@openwrt.org>> + struct > mt7530_priv *priv = container_of(dev, >> struct mt7530_priv, swdev); + + if (port >= >> MT7530_NUM_PORTS) -+ return -1; ++ return -EINVAL; ++ ++ >> if (pvid < > MT7530_MIN_VID || >> pvid > MT7530_MAX_VID) ++ return -EINVAL; + -+ >> priv->ports[port].pvid = pvid; ++ >> priv->port_entries[port].pvid = pvid; + + return 0; +} @@ >> -3042,26 +3080,38 @@ Signed-off-by: John Crispin >> <blo...@openwrt.org <mailto:blo...@openwrt.org>> +{ + > 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_VIDS) ++ 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; -+ >> > p->flags = 0; ++ >> ++ 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; @@ >> -3071,10 +3121,11 @@ Signed-off-by: John Crispin >> <blo...@openwrt.org > <mailto:blo...@openwrt.org>> >> +mt7530_set_vlan_ports(struct switch_dev *dev, struct switch_val >> *val) +{ + struct mt7530_priv *priv = container_of(dev, >> struct mt7530_priv, swdev); -+ int ports = 0; ++ u8 >> member = > 0; ++ u8 >> etags = 0; + int i; + -+ if (val->port_vlan < 0 || >> val->port_vlan >>> = MT7530_NUM_VIDS || ++ if (val->port_vlan < 0 || >>> val->port_vlan = MT7530_NUM_VLANS || + >>> val->len > > MT7530_NUM_PORTS) + return >> -EINVAL; + @@ -3084,90 +3135,135 @@ Signed-off-by: John Crispin >> <blo...@openwrt.org <mailto:blo...@openwrt.org>> + > if (p->id >= MT7530_NUM_PORTS) + return >> -EINVAL; + -+ ports |= BIT(p->id); ++ member |= > BIT(p->id); ++ ++ >> if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) ++ >> > etags |= >> BIT(p->id); + } -+ priv->vlans[val->port_vlan].ports = ports; >> ++ 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; ++ int i, j; + >> + if (!priv->global_vlan_enable) { -+ >> mt7530_w32(priv, 0x2004, 0xff000); -+ mt7530_w32(priv, >> 0x2104, 0xff000); -+ mt7530_w32(priv, 0x2204, 0xff000); -+ >> mt7530_w32(priv, 0x2304, 0xff000); -+ mt7530_w32(priv, >> 0x2404, 0xff000); -+ mt7530_w32(priv, 0x2504, 0xff000); -+ >> mt7530_w32(priv, 0x2604, 0xff000); -+ mt7530_w32(priv, >> 0x2010, 0x810000c); -+ mt7530_w32(priv, 0x2110, 0x810000c); -+ >> > mt7530_w32(priv, 0x2210, >> 0x810000c); -+ mt7530_w32(priv, 0x2310, >> 0x810000c); -+ mt7530_w32(priv, 0x2410, 0x810000c); -+ >> > mt7530_w32(priv, 0x2510, >> 0x810000c); -+ mt7530_w32(priv, 0x2610, >> 0x810000c); > -+ return 0; >> ++ for (i = 0; i < MT7530_NUM_PORTS; i++) ++ >> > mt7530_w32(priv, >> REG_ESW_PORT_PCR(i), 0x00ff0000); ++ ++ for (i = 0; >> i < MT7530_NUM_PORTS; i++) ++ >> mt7530_w32(priv, > REG_ESW_PORT_PVC(i), >> 0x8100000c); ++ ++ return 0; + } + -+ // LAN/WAN > ports as >> security mode -+ mt7530_w32(priv, 0x2004, 0xff0003); -+ >> mt7530_w32(priv, 0x2104, 0xff0003); -+ mt7530_w32(priv, >> 0x2204, 0xff0003); -+ mt7530_w32(priv, 0x2304, 0xff0003); -+ >> mt7530_w32(priv, 0x2404, 0xff0003); -+ mt7530_w32(priv, >> 0x2504, 0xff0003); -+ // LAN/WAN ports as transparent port -+ >> mt7530_w32(priv, 0x2010, 0x810000c0); -+ mt7530_w32(priv, >> 0x2110, 0x810000c0); -+ mt7530_w32(priv, 0x2210, >> 0x810000c0); -+ mt7530_w32(priv, 0x2310, 0x810000c0); -+ >> mt7530_w32(priv, 0x2410, 0x810000c0); -+ mt7530_w32(priv, >> 0x2510, 0x810000c0); -+ -+ > // set >> CPU/P7 port as user port -+ mt7530_w32(priv, 0x2610, >> 0x81000000); -+ mt7530_w32(priv, 0x2710, 0x81000000); -+ -+ >> mt7530_w32(priv, 0x2604, 0x20ff0003); -+ mt7530_w32(priv, >> 0x2704, 0x20ff0003); -+ mt7530_w32(priv, 0x2610, 0x81000000); ++ >> /* set all ports as security mode */ ++ for (i = 0; i < >> MT7530_NUM_PORTS; i++) ++ mt7530_w32(priv, REG_ESW_PORT_PCR(i), >> 0x00ff0003); ++ ++ /* > set all >> ports as user port */ ++ for (i = 0; i < MT7530_NUM_PORTS; > i++) ++ >> mt7530_w32(priv, REG_ESW_PORT_PVC(i), 0x81000000); + + >> for > (i = 0; >> i < MT7530_NUM_VLANS; i++) { -+ u8 ports = > priv->vlans[i].ports; >> -+ u32 val = mt7530_r32(priv, 0x100 + 4 * (i / 2)); >> ++ > 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 |= i; ++ val |= vid; + } else >> { + val &= 0xfff; -+ >> val > |= (i << 12); ++ val |= (vid << >> 12); + } -+ mt7530_w32(priv, 0x100 + 4 >> * > (i / 2), val); ++ >> mt7530_w32(priv, REG_ESW_VLAN_VTIM(i), val); + -+ if > (ports) -+ >> mt7530_w32(priv, REG_ESW_VLAN_VAWD1, BIT(30) | (ports << 16) | >> BIT(0)); ++ /* 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); + } + -+ for (i = 0; i < > MT7530_NUM_PORTS; >> i++) -+ mt7530_w32(priv, 0x2014 + (0x100 * i), >> 0x10000 | priv->ports[i].pvid); ++ /* 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 > switch_port_link *link) >> +{ + struct mt7530_priv *priv = container_of(dev, struct >> mt7530_priv, swdev); + u32 speed, pmsr; @@ -3216,6 >> +3312,14 @@ Signed-off-by: John Crispin <blo...@openwrt.org > <mailto:blo...@openwrt.org>> +}; + +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 mt7530_ops = { >> > > _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel