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

diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c 
b/target/linux/generic/files/drivers/net/phy/ar8216.c
index 3a696c2..1725161 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8216.c
+++ b/target/linux/generic/files/drivers/net/phy/ar8216.c
@@ -1894,6 +1894,117 @@ 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;
+       unsigned int pair;
+       u16 writes;
+
+       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);
+       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);
+
+               /* check for a still running test */
+               if (bus->read(bus, phy, AR8327_MII_CBLTEST_CTRL) & 0x1) {
+                       pr_err("switch: cable testing is busy [pair %i]", pair);
+                       continue;
+               }
+
+               /* 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,
@@ -2006,6 +2117,14 @@ static struct switch_attr ar8xxx_sw_attr_port[] = {
                .set = NULL,
                .get = ar8xxx_sw_get_port_mib,
        },
+       {
+               .type = SWITCH_TYPE_STRING,
+               .name = "cabletest",
+               .description = "Use set to start a cabletest on port and use"
+                               " get to fetch the result",
+               .set = ar8327_sw_cabletest_start,
+               .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
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to