Commit 1d1ae3c6 authored by Ioana Ciornei's avatar Ioana Ciornei Committed by Jakub Kicinski

net: phy: ti: 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: Dan Murphy <dmurphy@ti.com>
Signed-off-by: default avatarIoana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent a4d77421
...@@ -50,6 +50,14 @@ ...@@ -50,6 +50,14 @@
#define MII_DP83640_MISR_LINK_INT_EN 0x20 #define MII_DP83640_MISR_LINK_INT_EN 0x20
#define MII_DP83640_MISR_ED_INT_EN 0x40 #define MII_DP83640_MISR_ED_INT_EN 0x40
#define MII_DP83640_MISR_LQ_INT_EN 0x80 #define MII_DP83640_MISR_LQ_INT_EN 0x80
#define MII_DP83640_MISR_ANC_INT 0x400
#define MII_DP83640_MISR_DUP_INT 0x800
#define MII_DP83640_MISR_SPD_INT 0x1000
#define MII_DP83640_MISR_LINK_INT 0x2000
#define MII_DP83640_MISR_INT_MASK (MII_DP83640_MISR_ANC_INT |\
MII_DP83640_MISR_DUP_INT |\
MII_DP83640_MISR_SPD_INT |\
MII_DP83640_MISR_LINK_INT)
/* phyter seems to miss the mark by 16 ns */ /* phyter seems to miss the mark by 16 ns */
#define ADJTIME_FIX 16 #define ADJTIME_FIX 16
...@@ -1193,6 +1201,24 @@ static int dp83640_config_intr(struct phy_device *phydev) ...@@ -1193,6 +1201,24 @@ static int dp83640_config_intr(struct phy_device *phydev)
} }
} }
static irqreturn_t dp83640_handle_interrupt(struct phy_device *phydev)
{
int irq_status;
irq_status = phy_read(phydev, MII_DP83640_MISR);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}
if (!(irq_status & MII_DP83640_MISR_INT_MASK))
return IRQ_NONE;
phy_trigger_machine(phydev);
return IRQ_HANDLED;
}
static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
{ {
struct dp83640_private *dp83640 = struct dp83640_private *dp83640 =
...@@ -1517,6 +1543,7 @@ static struct phy_driver dp83640_driver = { ...@@ -1517,6 +1543,7 @@ static struct phy_driver dp83640_driver = {
.config_init = dp83640_config_init, .config_init = dp83640_config_init,
.ack_interrupt = dp83640_ack_interrupt, .ack_interrupt = dp83640_ack_interrupt,
.config_intr = dp83640_config_intr, .config_intr = dp83640_config_intr,
.handle_interrupt = dp83640_handle_interrupt,
}; };
static int __init dp83640_init(void) static int __init dp83640_init(void)
......
...@@ -303,6 +303,41 @@ static int dp83822_config_intr(struct phy_device *phydev) ...@@ -303,6 +303,41 @@ static int dp83822_config_intr(struct phy_device *phydev)
return phy_write(phydev, MII_DP83822_PHYSCR, physcr_status); return phy_write(phydev, MII_DP83822_PHYSCR, physcr_status);
} }
static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev)
{
int irq_status;
/* The MISR1 and MISR2 registers are holding the interrupt status in
* the upper half (15:8), while the lower half (7:0) is used for
* controlling the interrupt enable state of those individual interrupt
* sources. To determine the possible interrupt sources, just read the
* MISR* register and use it directly to know which interrupts have
* been enabled previously or not.
*/
irq_status = phy_read(phydev, MII_DP83822_MISR1);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}
if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
goto trigger_machine;
irq_status = phy_read(phydev, MII_DP83822_MISR2);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}
if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
goto trigger_machine;
return IRQ_NONE;
trigger_machine:
phy_trigger_machine(phydev);
return IRQ_HANDLED;
}
static int dp8382x_disable_wol(struct phy_device *phydev) static int dp8382x_disable_wol(struct phy_device *phydev)
{ {
int value = DP83822_WOL_EN | DP83822_WOL_MAGIC_EN | int value = DP83822_WOL_EN | DP83822_WOL_MAGIC_EN |
...@@ -576,6 +611,7 @@ static int dp83822_resume(struct phy_device *phydev) ...@@ -576,6 +611,7 @@ static int dp83822_resume(struct phy_device *phydev)
.set_wol = dp83822_set_wol, \ .set_wol = dp83822_set_wol, \
.ack_interrupt = dp83822_ack_interrupt, \ .ack_interrupt = dp83822_ack_interrupt, \
.config_intr = dp83822_config_intr, \ .config_intr = dp83822_config_intr, \
.handle_interrupt = dp83822_handle_interrupt, \
.suspend = dp83822_suspend, \ .suspend = dp83822_suspend, \
.resume = dp83822_resume, \ .resume = dp83822_resume, \
} }
...@@ -591,6 +627,7 @@ static int dp83822_resume(struct phy_device *phydev) ...@@ -591,6 +627,7 @@ static int dp83822_resume(struct phy_device *phydev)
.set_wol = dp83822_set_wol, \ .set_wol = dp83822_set_wol, \
.ack_interrupt = dp83822_ack_interrupt, \ .ack_interrupt = dp83822_ack_interrupt, \
.config_intr = dp83822_config_intr, \ .config_intr = dp83822_config_intr, \
.handle_interrupt = dp83822_handle_interrupt, \
.suspend = dp83822_suspend, \ .suspend = dp83822_suspend, \
.resume = dp83822_resume, \ .resume = dp83822_resume, \
} }
......
...@@ -37,6 +37,20 @@ ...@@ -37,6 +37,20 @@
DP83848_MISR_SPD_INT_EN | \ DP83848_MISR_SPD_INT_EN | \
DP83848_MISR_LINK_INT_EN) DP83848_MISR_LINK_INT_EN)
#define DP83848_MISR_RHF_INT BIT(8)
#define DP83848_MISR_FHF_INT BIT(9)
#define DP83848_MISR_ANC_INT BIT(10)
#define DP83848_MISR_DUP_INT BIT(11)
#define DP83848_MISR_SPD_INT BIT(12)
#define DP83848_MISR_LINK_INT BIT(13)
#define DP83848_MISR_ED_INT BIT(14)
#define DP83848_INT_MASK \
(DP83848_MISR_ANC_INT | \
DP83848_MISR_DUP_INT | \
DP83848_MISR_SPD_INT | \
DP83848_MISR_LINK_INT)
static int dp83848_ack_interrupt(struct phy_device *phydev) static int dp83848_ack_interrupt(struct phy_device *phydev)
{ {
int err = phy_read(phydev, DP83848_MISR); int err = phy_read(phydev, DP83848_MISR);
...@@ -66,6 +80,24 @@ static int dp83848_config_intr(struct phy_device *phydev) ...@@ -66,6 +80,24 @@ static int dp83848_config_intr(struct phy_device *phydev)
return phy_write(phydev, DP83848_MICR, control); return phy_write(phydev, DP83848_MICR, control);
} }
static irqreturn_t dp83848_handle_interrupt(struct phy_device *phydev)
{
int irq_status;
irq_status = phy_read(phydev, DP83848_MISR);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}
if (!(irq_status & DP83848_INT_MASK))
return IRQ_NONE;
phy_trigger_machine(phydev);
return IRQ_HANDLED;
}
static int dp83848_config_init(struct phy_device *phydev) static int dp83848_config_init(struct phy_device *phydev)
{ {
int val; int val;
...@@ -104,6 +136,7 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl); ...@@ -104,6 +136,7 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
/* IRQ related */ \ /* IRQ related */ \
.ack_interrupt = dp83848_ack_interrupt, \ .ack_interrupt = dp83848_ack_interrupt, \
.config_intr = dp83848_config_intr, \ .config_intr = dp83848_config_intr, \
.handle_interrupt = dp83848_handle_interrupt, \
} }
static struct phy_driver dp83848_driver[] = { static struct phy_driver dp83848_driver[] = {
......
...@@ -310,6 +310,30 @@ static int dp83867_config_intr(struct phy_device *phydev) ...@@ -310,6 +310,30 @@ static int dp83867_config_intr(struct phy_device *phydev)
return phy_write(phydev, MII_DP83867_MICR, micr_status); return phy_write(phydev, MII_DP83867_MICR, micr_status);
} }
static irqreturn_t dp83867_handle_interrupt(struct phy_device *phydev)
{
int irq_status, irq_enabled;
irq_status = phy_read(phydev, MII_DP83867_ISR);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}
irq_enabled = phy_read(phydev, MII_DP83867_MICR);
if (irq_enabled < 0) {
phy_error(phydev);
return IRQ_NONE;
}
if (!(irq_status & irq_enabled))
return IRQ_NONE;
phy_trigger_machine(phydev);
return IRQ_HANDLED;
}
static int dp83867_read_status(struct phy_device *phydev) static int dp83867_read_status(struct phy_device *phydev)
{ {
int status = phy_read(phydev, MII_DP83867_PHYSTS); int status = phy_read(phydev, MII_DP83867_PHYSTS);
...@@ -827,6 +851,7 @@ static struct phy_driver dp83867_driver[] = { ...@@ -827,6 +851,7 @@ static struct phy_driver dp83867_driver[] = {
/* IRQ related */ /* IRQ related */
.ack_interrupt = dp83867_ack_interrupt, .ack_interrupt = dp83867_ack_interrupt,
.config_intr = dp83867_config_intr, .config_intr = dp83867_config_intr,
.handle_interrupt = dp83867_handle_interrupt,
.suspend = genphy_suspend, .suspend = genphy_suspend,
.resume = genphy_resume, .resume = genphy_resume,
......
...@@ -207,6 +207,30 @@ static int dp83869_config_intr(struct phy_device *phydev) ...@@ -207,6 +207,30 @@ static int dp83869_config_intr(struct phy_device *phydev)
return phy_write(phydev, MII_DP83869_MICR, micr_status); return phy_write(phydev, MII_DP83869_MICR, micr_status);
} }
static irqreturn_t dp83869_handle_interrupt(struct phy_device *phydev)
{
int irq_status, irq_enabled;
irq_status = phy_read(phydev, MII_DP83869_ISR);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}
irq_enabled = phy_read(phydev, MII_DP83869_MICR);
if (irq_enabled < 0) {
phy_error(phydev);
return IRQ_NONE;
}
if (!(irq_status & irq_enabled))
return IRQ_NONE;
phy_trigger_machine(phydev);
return IRQ_HANDLED;
}
static int dp83869_set_wol(struct phy_device *phydev, static int dp83869_set_wol(struct phy_device *phydev,
struct ethtool_wolinfo *wol) struct ethtool_wolinfo *wol)
{ {
...@@ -852,6 +876,7 @@ static struct phy_driver dp83869_driver[] = { ...@@ -852,6 +876,7 @@ static struct phy_driver dp83869_driver[] = {
/* IRQ related */ /* IRQ related */
.ack_interrupt = dp83869_ack_interrupt, .ack_interrupt = dp83869_ack_interrupt,
.config_intr = dp83869_config_intr, .config_intr = dp83869_config_intr,
.handle_interrupt = dp83869_handle_interrupt,
.read_status = dp83869_read_status, .read_status = dp83869_read_status,
.get_tunable = dp83869_get_tunable, .get_tunable = dp83869_get_tunable,
......
...@@ -254,6 +254,49 @@ static int dp83811_config_intr(struct phy_device *phydev) ...@@ -254,6 +254,49 @@ static int dp83811_config_intr(struct phy_device *phydev)
return err; return err;
} }
static irqreturn_t dp83811_handle_interrupt(struct phy_device *phydev)
{
int irq_status;
/* The INT_STAT registers 1, 2 and 3 are holding the interrupt status
* in the upper half (15:8), while the lower half (7:0) is used for
* controlling the interrupt enable state of those individual interrupt
* sources. To determine the possible interrupt sources, just read the
* INT_STAT* register and use it directly to know which interrupts have
* been enabled previously or not.
*/
irq_status = phy_read(phydev, MII_DP83811_INT_STAT1);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}
if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
goto trigger_machine;
irq_status = phy_read(phydev, MII_DP83811_INT_STAT2);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}
if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
goto trigger_machine;
irq_status = phy_read(phydev, MII_DP83811_INT_STAT3);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}
if (irq_status & ((irq_status & GENMASK(7, 0)) << 8))
goto trigger_machine;
return IRQ_NONE;
trigger_machine:
phy_trigger_machine(phydev);
return IRQ_HANDLED;
}
static int dp83811_config_aneg(struct phy_device *phydev) static int dp83811_config_aneg(struct phy_device *phydev)
{ {
int value, err; int value, err;
...@@ -345,6 +388,7 @@ static struct phy_driver dp83811_driver[] = { ...@@ -345,6 +388,7 @@ static struct phy_driver dp83811_driver[] = {
.set_wol = dp83811_set_wol, .set_wol = dp83811_set_wol,
.ack_interrupt = dp83811_ack_interrupt, .ack_interrupt = dp83811_ack_interrupt,
.config_intr = dp83811_config_intr, .config_intr = dp83811_config_intr,
.handle_interrupt = dp83811_handle_interrupt,
.suspend = dp83811_suspend, .suspend = dp83811_suspend,
.resume = dp83811_resume, .resume = dp83811_resume,
}, },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment