net: dsa: microchip: ksz8795: add LINK_MD register support
authorOleksij Rempel <linux@rempel-privat.de>
Mon, 14 Jun 2021 04:31:23 +0000 (06:31 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 14 Jun 2021 19:54:43 +0000 (12:54 -0700)
Add mapping for LINK_MD register to enable cable testing functionality.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/microchip/ksz8795.c
drivers/net/dsa/microchip/ksz8795_reg.h

index 690304c87b02f50b8d8058a2310a12da04492d54..e1731ae4497d3dbb53d33a5d99d2a36301751fb8 100644 (file)
@@ -6,6 +6,7 @@
  *     Tristram Ha <Tristram.Ha@microchip.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/gpio.h>
@@ -729,6 +730,7 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
        u8 restart, speed, ctrl, link;
        const u8 *regs = ksz8->regs;
        int processed = true;
+       u8 val1, val2;
        u16 data = 0;
        u8 p = phy;
 
@@ -816,6 +818,22 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
                if (data & ~LPA_SLCT)
                        data |= LPA_LPACK;
                break;
+       case PHY_REG_LINK_MD:
+               ksz_pread8(dev, p, REG_PORT_LINK_MD_CTRL, &val1);
+               ksz_pread8(dev, p, REG_PORT_LINK_MD_RESULT, &val2);
+               if (val1 & PORT_START_CABLE_DIAG)
+                       data |= PHY_START_CABLE_DIAG;
+
+               if (val1 & PORT_CABLE_10M_SHORT)
+                       data |= PHY_CABLE_10M_SHORT;
+
+               data |= FIELD_PREP(PHY_CABLE_DIAG_RESULT_M,
+                               FIELD_GET(PORT_CABLE_DIAG_RESULT_M, val1));
+
+               data |= FIELD_PREP(PHY_CABLE_FAULT_COUNTER_M,
+                               (FIELD_GET(PORT_CABLE_FAULT_COUNTER_H, val1) << 8) |
+                               FIELD_GET(PORT_CABLE_FAULT_COUNTER_L, val2));
+               break;
        case PHY_REG_PHY_CTRL:
                ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
                if (link & PORT_MDIX_STATUS)
@@ -932,6 +950,10 @@ static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
                if (data != ctrl)
                        ksz_pwrite8(dev, p, regs[P_LOCAL_CTRL], data);
                break;
+       case PHY_REG_LINK_MD:
+               if (val & PHY_START_CABLE_DIAG)
+                       ksz_port_cfg(dev, p, REG_PORT_LINK_MD_CTRL, PORT_START_CABLE_DIAG, true);
+               break;
        default:
                break;
        }
index f925ddee52385adc8d6d46dd4473d99eb18dd140..a32355624f31f77b7c4e20f8f50c047368295ded 100644 (file)
 #define REG_PORT_4_LINK_MD_CTRL                0x4A
 
 #define PORT_CABLE_10M_SHORT           BIT(7)
-#define PORT_CABLE_DIAG_RESULT_M       0x3
+#define PORT_CABLE_DIAG_RESULT_M       GENMASK(6, 5)
 #define PORT_CABLE_DIAG_RESULT_S       5
 #define PORT_CABLE_STAT_NORMAL         0
 #define PORT_CABLE_STAT_OPEN           1
 #define PHY_REG_LINK_MD                        0x1D
 
 #define PHY_START_CABLE_DIAG           BIT(15)
+#define PHY_CABLE_DIAG_RESULT_M                GENMASK(14, 13)
 #define PHY_CABLE_DIAG_RESULT          0x6000
 #define PHY_CABLE_STAT_NORMAL          0x0000
 #define PHY_CABLE_STAT_OPEN            0x2000
 #define PHY_CABLE_STAT_SHORT           0x4000
 #define PHY_CABLE_STAT_FAILED          0x6000
 #define PHY_CABLE_10M_SHORT            BIT(12)
-#define PHY_CABLE_FAULT_COUNTER                0x01FF
+#define PHY_CABLE_FAULT_COUNTER_M      GENMASK(8, 0)
 
 #define PHY_REG_PHY_CTRL               0x1F