]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: phy: microchip_t1: Interrupt support for lan887x
authorDivya Koppera <divya.koppera@microchip.com>
Tue, 1 Oct 2024 14:44:21 +0000 (20:14 +0530)
committerJakub Kicinski <kuba@kernel.org>
Thu, 3 Oct 2024 23:22:12 +0000 (16:22 -0700)
Add support for link up and link down interrupts in lan887x.

Signed-off-by: Divya Koppera <divya.koppera@microchip.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Link: https://patch.msgid.link/20241001144421.6661-1-divya.koppera@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/phy/microchip_t1.c

index a5ef8fe50704678a8aad8988f8ae73d1bf97f792..f99f37634d5ece3b150be652f4a0ac8c26d251d0 100644 (file)
 #define MICROCHIP_CABLE_MAX_TIME_DIFF  \
        (MICROCHIP_CABLE_MIN_TIME_DIFF + MICROCHIP_CABLE_TIME_MARGIN)
 
+#define LAN887X_INT_STS                                0xf000
+#define LAN887X_INT_MSK                                0xf001
+#define LAN887X_INT_MSK_T1_PHY_INT_MSK         BIT(2)
+#define LAN887X_INT_MSK_LINK_UP_MSK            BIT(1)
+#define LAN887X_INT_MSK_LINK_DOWN_MSK          BIT(0)
+
+#define LAN887X_MX_CHIP_TOP_LINK_MSK   (LAN887X_INT_MSK_LINK_UP_MSK |\
+                                        LAN887X_INT_MSK_LINK_DOWN_MSK)
+
+#define LAN887X_MX_CHIP_TOP_ALL_MSK    (LAN887X_INT_MSK_T1_PHY_INT_MSK |\
+                                        LAN887X_MX_CHIP_TOP_LINK_MSK)
+
 #define DRIVER_AUTHOR  "Nisar Sayed <nisar.sayed@microchip.com>"
 #define DRIVER_DESC    "Microchip LAN87XX/LAN937x/LAN887x T1 PHY driver"
 
@@ -1474,6 +1486,49 @@ static void lan887x_get_strings(struct phy_device *phydev, u8 *data)
                ethtool_puts(&data, lan887x_hw_stats[i].string);
 }
 
+static int lan887x_config_intr(struct phy_device *phydev)
+{
+       int rc;
+
+       if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+               /* Clear the interrupt status before enabling interrupts */
+               rc = phy_read_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_STS);
+               if (rc < 0)
+                       return rc;
+
+               /* Unmask for enabling interrupt */
+               rc = phy_write_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_MSK,
+                                  (u16)~LAN887X_MX_CHIP_TOP_ALL_MSK);
+       } else {
+               rc = phy_write_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_MSK,
+                                  GENMASK(15, 0));
+               if (rc < 0)
+                       return rc;
+
+               rc = phy_read_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_STS);
+       }
+
+       return rc < 0 ? rc : 0;
+}
+
+static irqreturn_t lan887x_handle_interrupt(struct phy_device *phydev)
+{
+       int irq_status;
+
+       irq_status = phy_read_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_STS);
+       if (irq_status < 0) {
+               phy_error(phydev);
+               return IRQ_NONE;
+       }
+
+       if (irq_status & LAN887X_MX_CHIP_TOP_LINK_MSK) {
+               phy_trigger_machine(phydev);
+               return IRQ_HANDLED;
+       }
+
+       return IRQ_NONE;
+}
+
 static int lan887x_cd_reset(struct phy_device *phydev,
                            enum cable_diag_state cd_done)
 {
@@ -1504,6 +1559,10 @@ static int lan887x_cd_reset(struct phy_device *phydev,
                if (rc < 0)
                        return rc;
 
+               rc = lan887x_config_intr(phydev);
+               if (rc < 0)
+                       return rc;
+
                rc = lan887x_phy_reconfig(phydev);
                if (rc < 0)
                        return rc;
@@ -1881,6 +1940,8 @@ static struct phy_driver microchip_t1_phy_driver[] = {
                .read_status    = genphy_c45_read_status,
                .cable_test_start = lan887x_cable_test_start,
                .cable_test_get_status = lan887x_cable_test_get_status,
+               .config_intr    = lan887x_config_intr,
+               .handle_interrupt = lan887x_handle_interrupt,
        }
 };