[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