Commit 4567d5c3 authored by Ioana Ciornei's avatar Ioana Ciornei Committed by Jakub Kicinski
Browse files

net: phy: broadcom: implement generic .handle_interrupt() callback



In an attempt to actually support shared IRQs in phylib, we now move the
responsibility of triggering the phylib state machine or just returning
IRQ_NONE, based on the IRQ status register, to the PHY driver. Having
3 different IRQ handling callbacks (.handle_interrupt(),
.did_interrupt() and .ack_interrupt() ) is confusing so let the PHY
driver implement directly an IRQ handler like any other device driver.
Make this driver follow the new convention.

Cc: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarIoana Ciornei <ioana.ciornei@nxp.com>
Tested-by: default avatarMichael Walle <michael@walle.cc>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent e11ef96d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -258,6 +258,7 @@ static struct phy_driver bcm_cygnus_phy_driver[] = {
	.config_init   = bcm_cygnus_config_init,
	.ack_interrupt = bcm_phy_ack_intr,
	.config_intr   = bcm_phy_config_intr,
	.handle_interrupt = bcm_phy_handle_interrupt,
	.suspend       = genphy_suspend,
	.resume        = bcm_cygnus_resume,
}, {
+31 −0
Original line number Diff line number Diff line
@@ -196,6 +196,37 @@ int bcm_phy_config_intr(struct phy_device *phydev)
}
EXPORT_SYMBOL_GPL(bcm_phy_config_intr);

irqreturn_t bcm_phy_handle_interrupt(struct phy_device *phydev)
{
	int irq_status, irq_mask;

	irq_status = phy_read(phydev, MII_BCM54XX_ISR);
	if (irq_status < 0) {
		phy_error(phydev);
		return IRQ_NONE;
	}

	/* If a bit from the Interrupt Mask register is set, the corresponding
	 * bit from the Interrupt Status register is masked. So read the IMR
	 * and then flip the bits to get the list of possible interrupt
	 * sources.
	 */
	irq_mask = phy_read(phydev, MII_BCM54XX_IMR);
	if (irq_mask < 0) {
		phy_error(phydev);
		return IRQ_NONE;
	}
	irq_mask = ~irq_mask;

	if (!(irq_status & irq_mask))
		return IRQ_NONE;

	phy_trigger_machine(phydev);

	return IRQ_HANDLED;
}
EXPORT_SYMBOL_GPL(bcm_phy_handle_interrupt);

int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow)
{
	phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
+1 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ int bcm_phy_modify_rdb(struct phy_device *phydev, u16 rdb, u16 mask,

int bcm_phy_ack_intr(struct phy_device *phydev);
int bcm_phy_config_intr(struct phy_device *phydev);
irqreturn_t bcm_phy_handle_interrupt(struct phy_device *phydev);

int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down);

+21 −5
Original line number Diff line number Diff line
@@ -637,13 +637,29 @@ static int bcm54140_config_init(struct phy_device *phydev)
				  BCM54140_RDB_C_PWR_ISOLATE, 0);
}

static int bcm54140_did_interrupt(struct phy_device *phydev)
static irqreturn_t bcm54140_handle_interrupt(struct phy_device *phydev)
{
	int ret;
	int irq_status, irq_mask;

	irq_status = bcm_phy_read_rdb(phydev, BCM54140_RDB_ISR);
	if (irq_status < 0) {
		phy_error(phydev);
		return IRQ_NONE;
	}

	irq_mask = bcm_phy_read_rdb(phydev, BCM54140_RDB_IMR);
	if (irq_mask < 0) {
		phy_error(phydev);
		return IRQ_NONE;
	}
	irq_mask = ~irq_mask;

	if (!(irq_status & irq_mask))
		return IRQ_NONE;

	ret = bcm_phy_read_rdb(phydev, BCM54140_RDB_ISR);
	phy_trigger_machine(phydev);

	return (ret < 0) ? 0 : ret;
	return IRQ_HANDLED;
}

static int bcm54140_ack_intr(struct phy_device *phydev)
@@ -834,8 +850,8 @@ static struct phy_driver bcm54140_drivers[] = {
		.flags		= PHY_POLL_CABLE_TEST,
		.features       = PHY_GBIT_FEATURES,
		.config_init    = bcm54140_config_init,
		.did_interrupt	= bcm54140_did_interrupt,
		.ack_interrupt  = bcm54140_ack_intr,
		.handle_interrupt = bcm54140_handle_interrupt,
		.config_intr    = bcm54140_config_intr,
		.probe		= bcm54140_probe,
		.suspend	= genphy_suspend,
+2 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ static struct phy_driver bcm63xx_driver[] = {
	.config_init	= bcm63xx_config_init,
	.ack_interrupt	= bcm_phy_ack_intr,
	.config_intr	= bcm63xx_config_intr,
	.handle_interrupt = bcm_phy_handle_interrupt,
}, {
	/* same phy as above, with just a different OUI */
	.phy_id		= 0x002bdc00,
@@ -79,6 +80,7 @@ static struct phy_driver bcm63xx_driver[] = {
	.config_init	= bcm63xx_config_init,
	.ack_interrupt	= bcm_phy_ack_intr,
	.config_intr	= bcm63xx_config_intr,
	.handle_interrupt = bcm_phy_handle_interrupt,
} };

module_phy_driver(bcm63xx_driver);
Loading