[OpenWrt-Devel] [PATCH] Update MT7530 switch driver.
John Crispin
john at phrozen.org
Tue Jun 24 08:54:11 EDT 2014
Hi,
On 21/06/2014 17:10, xfguo at credosemi.com wrote:
> From: Xiongfei Guo <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>
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> +#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> +#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> + 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> + + 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> +{ + 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> +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> + 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> + 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> + 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> + 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> +{ + 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>
> +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> + 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> +}; + +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