arch/arm/imxrt: a fixed link when no PHY answers

A carrier with a switch port wired MAC to MAC has no PHY on MDIO, and
ifup failed. With IMXRT_ENET_FIXED_LINK the configured PHY, or the
board's PHY list, is tried first; if none answers the MAC runs at
100 Mbps full duplex and SIOCGMIIREG reports the link up, so the
network monitor keeps the interface up.

Signed-off-by: Royyan Zahir <royzah@gmail.com>
This commit is contained in:
Royyan Zahir 2026-10-04 18:50:46 +04:00 • committed by Alan C. Assis
parent a6f5b1b2b5
commit eafd01cecc
2 changed files with 60 additions and 3 deletions

View file

@ -2693,6 +2693,14 @@ config IMXRT_ENET_PHYINIT
imxrt_phy_boardinitialize(); The i.MXRT ENET driver will call this
function one time before it first uses the PHY.
config IMXRT_ENET_FIXED_LINK
bool "Fixed link when no PHY answers"
default n
depends on IMXRT_ENET
---help---
If no PHY answers on MDIO, run the MAC at 100 Mbps full duplex
instead of failing ifup, for a switch port wired MAC to MAC.
config IMXRT_PHY_POLLING
bool "Support network monitoring by polling the PHY"
default n

View file

@ -397,6 +397,9 @@ struct imxrt_driver_s
#if defined(CONFIG_ETH0_PHY_MULTI)
uint8_t current_phy; /* The index of the PHY being used */
uint8_t current_phy_address; /* The address of the PHY being used */
#endif
#ifdef CONFIG_IMXRT_ENET_FIXED_LINK
bool fixed_link; /* No PHY answered: 100 Mbps full duplex */
#endif
/* This holds the information visible to the NuttX network */
@ -1416,16 +1419,38 @@ static int imxrt_ifup_action(struct net_driver_s *dev, bool resetphy)
/* Configure the PHY */
#ifdef CONFIG_IMXRT_ENET_FIXED_LINK
priv->fixed_link = false;
#endif
#if defined(CONFIG_ETH0_PHY_MULTI)
ret = imxrt_determine_phy(priv);
if (ret < 0)
{
# ifdef CONFIG_IMXRT_ENET_FIXED_LINK
priv->fixed_link = true;
# else
nerr("ERROR: Failed to determine the PHY: %d\n", ret);
return ret;
# endif
}
#endif
ret = imxrt_initphy(priv, resetphy);
#ifdef CONFIG_IMXRT_ENET_FIXED_LINK
if (ret == -ENOENT && !priv->fixed_link)
{
priv->fixed_link = true;
ret = imxrt_initphy(priv, false);
}
if (priv->fixed_link)
{
nwarn("WARNING: no PHY answered, fixed 100 Mbps full duplex link\n");
}
#endif
if (ret < 0)
{
nerr("ERROR: Failed to configure the PHY: %d\n", ret);
@ -1922,6 +1947,16 @@ static int imxrt_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg)
{
struct mii_ioctl_data_s *req =
(struct mii_ioctl_data_s *)((uintptr_t)arg);
#ifdef CONFIG_IMXRT_ENET_FIXED_LINK
if (priv->fixed_link)
{
req->val_out = req->reg_num == MII_MSR ?
MII_MSR_LINKSTATUS | MII_MSR_100BASETXFULL : 0;
ret = OK;
break;
}
#endif
#if defined(CLAUSE45)
if (
# if defined(CONFIG_ETH0_PHY_MULTI)
@ -2539,6 +2574,16 @@ static inline int imxrt_initphy(struct imxrt_driver_s *priv, bool renogphy)
uint8_t phyaddr = BOARD_PHY_ADDR;
int retries;
int ret;
bool fixed = false;
#ifdef CONFIG_IMXRT_ENET_FIXED_LINK
fixed = priv->fixed_link;
phydata = 0;
if (fixed)
{
goto mac_setup;
}
#endif
if (renogphy)
{
@ -2866,6 +2911,10 @@ static inline int imxrt_initphy(struct imxrt_driver_s *priv, bool renogphy)
# if defined(CONFIG_ETH0_PHY_MULTI)
}
# endif
#endif
#ifdef CONFIG_IMXRT_ENET_FIXED_LINK
mac_setup:
#endif
/* Set up the transmit and receive control registers based on the
@ -2898,7 +2947,7 @@ static inline int imxrt_initphy(struct imxrt_driver_s *priv, bool renogphy)
/* Setup half or full duplex */
if (BOARD_PHY_ISDUPLEX(phydata))
if (fixed || BOARD_PHY_ISDUPLEX(phydata))
{
/* Full duplex */
@ -2913,14 +2962,14 @@ static inline int imxrt_initphy(struct imxrt_driver_s *priv, bool renogphy)
rcr |= ENET_RCR_DRT;
}
if (BOARD_PHY_10BASET(phydata))
if (!fixed && BOARD_PHY_10BASET(phydata))
{
/* 10 Mbps */
ninfo("%s: 10 Base-T\n", BOARD_PHY_NAME);
rcr |= ENET_RCR_RMII_10T;
}
else if (BOARD_PHY_100BASET(phydata))
else if (fixed || BOARD_PHY_100BASET(phydata))
{
/* 100 Mbps */