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