[OpenWrt-Devel] [PATCH] Update MT7530 switch driver.

John Crispin john at phrozen.org
Tue Jun 24 10:32:10 EDT 2014



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 <john at phrozen.org 
> <mailto:john at phrozen.org>> wrote:
> 
> Hi,
> 
> On 21/06/2014 17:10, xfguo at credosemi.com 
> <mailto:xfguo at credosemi.com> wrote:
>> From: Xiongfei Guo <xfguo at credosemi.com
>> <mailto:xfguo at 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 <xfguo at credosemi.com
> <mailto:xfguo at 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
>> <blogic at openwrt.org <mailto:blogic at 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 <blogic at openwrt.org <mailto:blogic at 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 <blogic at openwrt.org <mailto:blogic at 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 
>> <blogic at openwrt.org <mailto:blogic at 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 <blogic at openwrt.org <mailto:blogic at 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 <blogic at openwrt.org
> <mailto:blogic at 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 <blogic at openwrt.org
> <mailto:blogic at 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 
>> <blogic at openwrt.org <mailto:blogic at 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 
>> <blogic at openwrt.org <mailto:blogic at 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 <blogic at openwrt.org
>> <mailto:blogic at 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
>> <blogic at openwrt.org <mailto:blogic at 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
>> <blogic at openwrt.org
> <mailto:blogic at 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 
>> <blogic at openwrt.org <mailto:blogic at 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 <blogic at openwrt.org
> <mailto:blogic at 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 at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list