summaryrefslogtreecommitdiff
path: root/drivers/net/phy
diff options
context:
space:
mode:
authorHeiner Kallweit <hkallweit1@gmail.com>2022-03-03 08:54:15 +0100
committerJakub Kicinski <kuba@kernel.org>2022-03-04 21:03:45 -0800
commita502a8f04097e038c3daa16c5202a9538116d563 (patch)
tree8ad3b8847862969ec633bbeab98f0b5835eab8d0 /drivers/net/phy
parentbe4977b847f5d5cedb64d50eaaf2218c3a55a3a3 (diff)
net: phy: meson-gxl: fix interrupt handling in forced mode
This PHY doesn't support a link-up interrupt source. If aneg is enabled we use the "aneg complete" interrupt for this purpose, but if aneg is disabled link-up isn't signaled currently. According to a vendor driver there's an additional "energy detect" interrupt source that can be used to signal link-up if aneg is disabled. We can safely ignore this interrupt source if aneg is enabled. This patch was tested on a TX3 Mini TV box with S905W (even though boot message says it's a S905D). This issue has been existing longer, but due to changes in phylib and the driver the patch applies only from the commit marked as fixed. Fixes: 84c8f773d2dc ("net: phy: meson-gxl: remove the use of .ack_callback()") Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Link: https://lore.kernel.org/r/04cac530-ea1b-850e-6cfa-144a55c4d75d@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/phy')
-rw-r--r--drivers/net/phy/meson-gxl.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/net/phy/meson-gxl.c b/drivers/net/phy/meson-gxl.c
index 7e7904fee1d9..c49062ad72c6 100644
--- a/drivers/net/phy/meson-gxl.c
+++ b/drivers/net/phy/meson-gxl.c
@@ -30,8 +30,12 @@
#define INTSRC_LINK_DOWN BIT(4)
#define INTSRC_REMOTE_FAULT BIT(5)
#define INTSRC_ANEG_COMPLETE BIT(6)
+#define INTSRC_ENERGY_DETECT BIT(7)
#define INTSRC_MASK 30
+#define INT_SOURCES (INTSRC_LINK_DOWN | INTSRC_ANEG_COMPLETE | \
+ INTSRC_ENERGY_DETECT)
+
#define BANK_ANALOG_DSP 0
#define BANK_WOL 1
#define BANK_BIST 3
@@ -200,7 +204,6 @@ static int meson_gxl_ack_interrupt(struct phy_device *phydev)
static int meson_gxl_config_intr(struct phy_device *phydev)
{
- u16 val;
int ret;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
@@ -209,16 +212,9 @@ static int meson_gxl_config_intr(struct phy_device *phydev)
if (ret)
return ret;
- val = INTSRC_ANEG_PR
- | INTSRC_PARALLEL_FAULT
- | INTSRC_ANEG_LP_ACK
- | INTSRC_LINK_DOWN
- | INTSRC_REMOTE_FAULT
- | INTSRC_ANEG_COMPLETE;
- ret = phy_write(phydev, INTSRC_MASK, val);
+ ret = phy_write(phydev, INTSRC_MASK, INT_SOURCES);
} else {
- val = 0;
- ret = phy_write(phydev, INTSRC_MASK, val);
+ ret = phy_write(phydev, INTSRC_MASK, 0);
/* Ack any pending IRQ */
ret = meson_gxl_ack_interrupt(phydev);
@@ -237,9 +233,16 @@ static irqreturn_t meson_gxl_handle_interrupt(struct phy_device *phydev)
return IRQ_NONE;
}
+ irq_status &= INT_SOURCES;
+
if (irq_status == 0)
return IRQ_NONE;
+ /* Aneg-complete interrupt is used for link-up detection */
+ if (phydev->autoneg == AUTONEG_ENABLE &&
+ irq_status == INTSRC_ENERGY_DETECT)
+ return IRQ_HANDLED;
+
phy_trigger_machine(phydev);
return IRQ_HANDLED;