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: Ioana Ciornei <ioana.ciornei@nxp.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Родитель
a4d7742149
Коммит
1d1ae3c6ca
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 = {
|
||||||
.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)
|
||||||
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)
|
||||||
.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)
|
||||||
.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 @@
|
||||||
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)
|
||||||
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);
|
||||||
/* 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)
|
||||||
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[] = {
|
||||||
/* 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)
|
||||||
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[] = {
|
||||||
/* 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)
|
||||||
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[] = {
|
||||||
.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,
|
||||||
},
|
},
|
||||||
|
|
Загрузка…
Ссылка в новой задаче