summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar7240.c67
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 8e1584999b..22240902b5 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[] = {