提交 1d1ae3c6 编写于 作者: I Ioana Ciornei 提交者: 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: NIoana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: NJakub Kicinski <kuba@kernel.org>
上级 a4d77421
......@@ -50,6 +50,14 @@
#define MII_DP83640_MISR_LINK_INT_EN 0x20
#define MII_DP83640_MISR_ED_INT_EN 0x40
#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 */
#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)
{
struct dp83640_private *dp83640 =
......@@ -1517,6 +1543,7 @@ static struct phy_driver dp83640_driver = {
.config_init = dp83640_config_init,
.ack_interrupt = dp83640_ack_interrupt,
.config_intr = dp83640_config_intr,
.handle_interrupt = dp83640_handle_interrupt,
};
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);
}
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)
{
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, \
.ack_interrupt = dp83822_ack_interrupt, \
.config_intr = dp83822_config_intr, \
.handle_interrupt = dp83822_handle_interrupt, \
.suspend = dp83822_suspend, \
.resume = dp83822_resume, \
}
......@@ -591,6 +627,7 @@ static int dp83822_resume(struct phy_device *phydev)
.set_wol = dp83822_set_wol, \
.ack_interrupt = dp83822_ack_interrupt, \
.config_intr = dp83822_config_intr, \
.handle_interrupt = dp83822_handle_interrupt, \
.suspend = dp83822_suspend, \
.resume = dp83822_resume, \
}
......
......@@ -37,6 +37,20 @@
DP83848_MISR_SPD_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)
{
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);
}
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)
{
int val;
......@@ -104,6 +136,7 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
/* IRQ related */ \
.ack_interrupt = dp83848_ack_interrupt, \
.config_intr = dp83848_config_intr, \
.handle_interrupt = dp83848_handle_interrupt, \
}
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);
}
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)
{
int status = phy_read(phydev, MII_DP83867_PHYSTS);
......@@ -827,6 +851,7 @@ static struct phy_driver dp83867_driver[] = {
/* IRQ related */
.ack_interrupt = dp83867_ack_interrupt,
.config_intr = dp83867_config_intr,
.handle_interrupt = dp83867_handle_interrupt,
.suspend = genphy_suspend,
.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);
}
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,
struct ethtool_wolinfo *wol)
{
......@@ -852,6 +876,7 @@ static struct phy_driver dp83869_driver[] = {
/* IRQ related */
.ack_interrupt = dp83869_ack_interrupt,
.config_intr = dp83869_config_intr,
.handle_interrupt = dp83869_handle_interrupt,
.read_status = dp83869_read_status,
.get_tunable = dp83869_get_tunable,
......
......@@ -254,6 +254,49 @@ static int dp83811_config_intr(struct phy_device *phydev)
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)
{
int value, err;
......@@ -345,6 +388,7 @@ static struct phy_driver dp83811_driver[] = {
.set_wol = dp83811_set_wol,
.ack_interrupt = dp83811_ack_interrupt,
.config_intr = dp83811_config_intr,
.handle_interrupt = dp83811_handle_interrupt,
.suspend = dp83811_suspend,
.resume = dp83811_resume,
},
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册