phy: nxp-c45-tja11xx: add interrupt support
authorRadu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com>
Fri, 23 Apr 2021 15:00:50 +0000 (18:00 +0300)
committerDavid S. Miller <davem@davemloft.net>
Fri, 23 Apr 2021 21:13:16 +0000 (14:13 -0700)
Added .config_intr and .handle_interrupt callbacks.

Link event interrupt will trigger an interrupt every time when the link
goes up or down.

Signed-off-by: Radu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/nxp-c45-tja11xx.c

index 95307097ebfff545dfb119e4c50376760cbebe36..26b9c0d7cb9d5f47464b9be335a96878610afcbb 100644 (file)
 #define DEVICE_CONTROL_CONFIG_GLOBAL_EN        BIT(14)
 #define DEVICE_CONTROL_CONFIG_ALL_EN   BIT(13)
 
+#define VEND1_PHY_IRQ_ACK              0x80A0
+#define VEND1_PHY_IRQ_EN               0x80A1
+#define VEND1_PHY_IRQ_STATUS           0x80A2
+#define PHY_IRQ_LINK_EVENT             BIT(1)
+
 #define VEND1_PHY_CONTROL              0x8100
 #define PHY_CONFIG_EN                  BIT(14)
 #define PHY_START_OP                   BIT(0)
@@ -188,6 +193,32 @@ static int nxp_c45_start_op(struct phy_device *phydev)
                                PHY_START_OP);
 }
 
+static int nxp_c45_config_intr(struct phy_device *phydev)
+{
+       if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+               return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+                                       VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT);
+       else
+               return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+                                         VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT);
+}
+
+static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev)
+{
+       irqreturn_t ret = IRQ_NONE;
+       int irq;
+
+       irq = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_STATUS);
+       if (irq & PHY_IRQ_LINK_EVENT) {
+               phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_PHY_IRQ_ACK,
+                             PHY_IRQ_LINK_EVENT);
+               phy_trigger_machine(phydev);
+               ret = IRQ_HANDLED;
+       }
+
+       return ret;
+}
+
 static int nxp_c45_soft_reset(struct phy_device *phydev)
 {
        int ret;
@@ -560,6 +591,8 @@ static struct phy_driver nxp_c45_driver[] = {
                .soft_reset             = nxp_c45_soft_reset,
                .config_aneg            = nxp_c45_config_aneg,
                .config_init            = nxp_c45_config_init,
+               .config_intr            = nxp_c45_config_intr,
+               .handle_interrupt       = nxp_c45_handle_interrupt,
                .read_status            = nxp_c45_read_status,
                .suspend                = genphy_c45_pma_suspend,
                .resume                 = genphy_c45_pma_resume,