Commit 5fad1c1a authored by Divya Koppera's avatar Divya Koppera Committed by Jakub Kicinski
Browse files

net: phy: microchip_t1: Interrupt support for lan887x

parent 046e64f5
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
@@ -226,6 +226,18 @@
#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,
	}
};