diff options
Diffstat (limited to 'target/linux/ar71xx/files/drivers')
| -rw-r--r-- | target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c | 67 | 
1 files changed, 67 insertions, 0 deletions
diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c index 8e1584999..22240902b 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c @@ -96,6 +96,7 @@  #define AR7240_REG_PORT_BASE(_port)	(0x100 + (_port) * 0x100)  #define AR7240_REG_PORT_STATUS(_port)	(AR7240_REG_PORT_BASE((_port)) + 0x00) +#define AR7240_PORT_STATUS_SPEED_S	0  #define AR7240_PORT_STATUS_SPEED_M	BITM(2)  #define AR7240_PORT_STATUS_SPEED_10	0  #define AR7240_PORT_STATUS_SPEED_100	1 @@ -207,6 +208,7 @@ struct ar7240sw {  	u8 vlan_table[AR7240_MAX_VLANS];  	u8 vlan_tagged;  	u16 pvid[AR7240_NUM_PORTS]; +	char buf[80];  };  struct ar7240sw_hw_stat { @@ -645,6 +647,63 @@ ar7240_get_vlan(struct switch_dev *dev, const struct switch_attr *attr,  	return 0;  } +static const char * +ar7240_speed_str(u32 status) +{ +	u32 speed; + +	speed = (status >> AR7240_PORT_STATUS_SPEED_S) & +					AR7240_PORT_STATUS_SPEED_M; +	switch (speed) { +	case AR7240_PORT_STATUS_SPEED_10: +		return "10baseT"; +	case AR7240_PORT_STATUS_SPEED_100: +		return "100baseT"; +	case AR7240_PORT_STATUS_SPEED_1000: +		return "1000baseT"; +	} + +	return "unknown"; +} + +static int +ar7240_port_get_link(struct switch_dev *dev, const struct switch_attr *attr, +		     struct switch_val *val) +{ +	struct ar7240sw *as = sw_to_ar7240(dev); +	struct mii_bus *mii = as->mii_bus; +	u32 len; +	u32 status; +	int port; + +	port = val->port_vlan; + +	memset(as->buf, '\0', sizeof(as->buf)); +	status = ar7240sw_reg_read(mii, AR7240_REG_PORT_STATUS(port)); + +	if (status & AR7240_PORT_STATUS_LINK_UP) { +		len = snprintf(as->buf, sizeof(as->buf), +				"port:%d link:up speed:%s %s-duplex %s%s%s", +				port, +				ar7240_speed_str(status), +				(status & AR7240_PORT_STATUS_DUPLEX) ? +					"full" : "half", +				(status & AR7240_PORT_STATUS_TXFLOW) ? +					"txflow ": "", +				(status & AR7240_PORT_STATUS_RXFLOW) ? +					"rxflow " : "", +				(status & AR7240_PORT_STATUS_LINK_AUTO) ? +					"auto ": ""); +	} else { +		len = snprintf(as->buf, sizeof(as->buf), +			       "port:%d link:down", port); +	} + +	val->value.s = as->buf; +	val->len = len; + +	return 0; +}  static void  ar7240_vtu_op(struct ar7240sw *as, u32 op, u32 val) @@ -733,6 +792,14 @@ static struct switch_attr ar7240_globals[] = {  };  static struct switch_attr ar7240_port[] = { +	{ +		.type = SWITCH_TYPE_STRING, +		.name = "link", +		.description = "Get port link information", +		.max = 1, +		.set = NULL, +		.get = ar7240_port_get_link, +	},  };  static struct switch_attr ar7240_vlan[] = {  | 
