A cable test is a async job for the switch.
swconfig dev switch0 port 1 set cabletest # start
swconfig dev switch0 port 1 get cableresult # get results

Signed-off-by: Alexander Couzens <[email protected]>
---
 .../linux/generic/files/drivers/net/phy/ar8216.c   | 111 +++++++++++++++++++++
 .../linux/generic/files/drivers/net/phy/ar8216.h   |   7 ++
 2 files changed, 118 insertions(+)

diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c 
b/target/linux/generic/files/drivers/net/phy/ar8216.c
index ccc074f..fc27000 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8216.c
+++ b/target/linux/generic/files/drivers/net/phy/ar8216.c
@@ -1653,6 +1653,105 @@ unlock:
        return ret;
 }
 
+static int
+ar8327_sw_cabletest_start(struct switch_dev *dev,
+                          const struct switch_attr *attr,
+                          struct switch_val *val)
+{
+       struct mii_bus *bus = swdev_to_ar8xxx(dev)->phy->bus;
+       // port 1 = phy 0
+       int phy = val->port_vlan -1;
+
+       if(!chip_is_ar8327(swdev_to_ar8xxx(dev)))
+       {
+               pr_info("switch: Only ar8327 is supported for cable testing\n");
+               return -EINVAL;
+       }
+
+       if (phy < 0 || phy >= AR8327_NUM_PHYS) {
+               return -EINVAL;
+       }
+
+       mutex_lock(&bus->mdio_lock);
+       // check for a still running test
+       if(bus->read(bus, phy, AR8327_MII_CBLTEST_CTRL) & 0x1) {
+               mutex_unlock(&bus->mdio_lock);
+               return -EINVAL;
+       }
+
+       // start cable test
+       bus->write(bus, phy, AR8327_MII_CBLTEST_CTRL, 0x1);
+       mutex_unlock(&bus->mdio_lock);
+
+       return 0;
+}
+
+static int
+ar8327_sw_cabletest_get(struct switch_dev *dev,
+                          const struct switch_attr *attr,
+                          struct switch_val *val)
+{
+       struct mii_bus *bus = swdev_to_ar8xxx(dev)->phy->bus;
+       u16 reads;
+       u16 writes;
+       unsigned int pair;
+       /* length multiply *0.824m */
+       u8 cablelength;
+       u8 state;
+       char buf[2048];
+       int len = 0;
+       // port 1 = phy 0
+       int phy = val->port_vlan -1;
+
+       if(!chip_is_ar8327(swdev_to_ar8xxx(dev)))
+       {
+               pr_info("switch: Only ar8327 is supported for cable testing\n");
+               return -EINVAL;
+       }
+
+       if (phy < 0 || phy >= AR8327_NUM_PHYS)
+               return -EINVAL;
+
+       mutex_lock(&bus->mdio_lock);
+
+       // check active cable test
+       reads = bus->read(bus, phy, AR8327_MII_CBLTEST_CTRL);
+       if (reads & 0x1) {
+               len += snprintf(buf + len, sizeof(buf) - len, "Error: Cabletest 
still running\n");
+               goto out;
+       }
+
+       for (pair = 0; pair < 4 ; pair++) {
+               writes = pair << AR8327_CBLTEST_CTRL_SELECT_BIT;
+               bus->write(bus, phy, AR8327_MII_CBLTEST_CTRL, pair << 
AR8327_CBLTEST_CTRL_SELECT_BIT);
+               usleep_range(1000, 2000); /* wait for the switch to propagate */
+               reads = bus->read(bus, phy, AR8327_MII_CBLTEST_RESULTS);
+               cablelength = reads & 0xFF;
+               state = reads >> AR8327_CBLTEST_CTRL_STATUS_BIT;
+               len += snprintf(buf + len, sizeof(buf) - len, "pair %i, len %i 
(0.824m), state ", pair, cablelength);
+               switch(state) {
+                       case AR8327_CBLTEST_CTRL_STATUS_OK:
+                               len += snprintf(buf + len, sizeof(buf) - len, 
"ok, no link\n");
+                               break;
+                       case AR8327_CBLTEST_CTRL_STATUS_LINK:
+                               len += snprintf(buf + len, sizeof(buf) - len, 
"link up\n");
+                               break;
+                       default:
+                               len += snprintf(buf + len, sizeof(buf) - len, 
"broken 0x%x\n", state);
+                               break;
+               }
+       }
+
+out:
+       mutex_unlock(&bus->mdio_lock);
+
+       val->value.s = buf;
+       val->len = len;
+       return 0;
+}
+
+
+
 static struct switch_attr ar8xxx_sw_attr_globals[] = {
        {
                .type = SWITCH_TYPE_INT,
@@ -1685,6 +1784,18 @@ static struct switch_attr ar8xxx_sw_attr_port[] = {
                .set = NULL,
                .get = ar8xxx_sw_get_port_mib,
        },
+       {
+               .type = SWITCH_TYPE_NOVAL,
+               .name = "cabletest",
+               .description = "Start a cabletest on port",
+               .set = ar8327_sw_cabletest_start,
+       },
+       {
+               .type = SWITCH_TYPE_STRING,
+               .name = "cableresult",
+               .description = "Get results of cabletest",
+               .get = ar8327_sw_cabletest_get,
+       },
 };
 
 static struct switch_attr ar8xxx_sw_attr_vlan[] = {
diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.h 
b/target/linux/generic/files/drivers/net/phy/ar8216.h
index 95d9a96..709d127 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8216.h
+++ b/target/linux/generic/files/drivers/net/phy/ar8216.h
@@ -438,6 +438,13 @@
 
 #define AR8327_REG_PORT_STATS_BASE(_i)         (0x1000 + (_i) * 0x100)
 
+#define AR8327_MII_CBLTEST_CTRL 0x16
+#define   AR8327_CBLTEST_CTRL_SELECT_BIT 0x8
+#define AR8327_MII_CBLTEST_RESULTS 0x1c
+#define   AR8327_CBLTEST_CTRL_STATUS_BIT 0x8
+#define     AR8327_CBLTEST_CTRL_STATUS_OK 0x0
+#define     AR8327_CBLTEST_CTRL_STATUS_LINK 0x3
+
 /* port speed */
 enum {
         AR8216_PORT_SPEED_10M = 0,
-- 
1.8.2

_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to