arm64/imx9: Support & configure RGMII-ID on RTL8211F

For the RTL8211F PHY, configuration of RX/TXDLY was missing.
At least on my i.MX93 EVK, this is necessary for transmission
to work (RXDLY defaults to true on the PHY).

This commit brings support for RGMII internal delay configuration
(on or off for both directions) and enables it on the i.MX93 EVK
board. The introduced Kconfig is set to default to 'n', to avoid
breaking the functionality of other, out-of-tree boards based on
i.MX93, running the RTL8211F PHY, or to avoid introducing
unnecessary code on boards running other PHYs.

Configuration of internal delay on other PHYs is not
implemented, and results in a warning (but no error).

Signed-off-by: George Poulios <gpoulios@census-labs.com>
This commit is contained in:
George Poulios 2025-06-04 11:33:35 +03:00 committed by Xiang Xiao
parent e540fae8b3
commit 03f7f59fa8
6 changed files with 134 additions and 1 deletions

View file

@ -1003,6 +1003,21 @@ config IMX9_ENET1_RGMII
endchoice
if IMX9_ENET1_RGMII
config IMX9_ENET1_RGMII_ID
bool "Enable the PHY internal delay on both TX & RX signals"
default n
depends on IMX9_ENET1_RGMII
---help---
In RGMII-ID mode, the PHY introduces an internal delay eliminating
the need for a timing skew between the data and clock signals otherwise
generated by the PCB design. This is currently only implemented for the
RTL8211F chip; enabling or disabling it on any other PHYs will not make
any difference.
endif # IMX9_ENET1_RGMII
config IMX9_ENET1_TX_CLOCK_IS_INPUT
bool "ENET1 TX clock is input"
default y if IMX9_ENET1_RMII

View file

@ -277,6 +277,11 @@ static int imx9_writemii(struct imx9_driver_s *priv, uint8_t regaddr,
uint16_t data);
static int imx9_readmii(struct imx9_driver_s *priv, uint8_t regaddr,
uint16_t *data);
#ifdef CONFIG_IMX9_ENET1_RGMII
static int imx9_config_rgmii_id(struct imx9_driver_s *priv);
#else
# define imx9_config_rgmii_id(priv) (OK)
#endif
static int imx9_initphy(struct imx9_driver_s *priv, bool renogphy);
static int imx9_readmmd(struct imx9_driver_s *priv, uint8_t mmd,
@ -2677,6 +2682,102 @@ static int imx9_phy_wait_autoneg_complete(struct imx9_driver_s *priv)
return imx9_read_phy_status(priv);
}
/****************************************************************************
* Function: imx9_config_rgmii_id
*
* Description:
* Configure the PHY internal delay. Currently only supported on RTL8211F.
* If CONFIG_IMX9_ENET1_RGMII_ID is set, this function sets both TXDLY
* and RXDLY bit on MIICR1 and MIICR2 respectively. Otherwise, it clears
* the respective bits.
*
* Input Parameters:
* priv - Reference to the private ENET driver state structure
*
* Returned Value:
* Zero (OK) returned on success; a negated errno value is returned on any
* failure;
*
****************************************************************************/
#ifdef CONFIG_IMX9_ENET1_RGMII
static int imx9_config_rgmii_id(struct imx9_driver_s *priv)
{
int ret;
uint16_t prev_page;
uint16_t reg;
if (!imx9_phy_is(priv, GMII_RTL8211F_NAME))
{
nwarn("WARN: not configuring RGMII Internal Delay on %s phy\n",
priv->cur_phy->name);
return OK;
}
ret = imx9_readmii(priv, GMII_RTL8211F_PAGSR, &prev_page);
if (ret < 0)
{
nerr("ERROR: Getting page, imx9_readmii failed: %d\n", ret);
goto errout;
}
ret = imx9_writemii(priv, GMII_RTL8211F_PAGSR, 0xd08);
if (ret < 0)
{
nerr("ERROR: Selecting page, imx9_writemii failed: %d\n", ret);
goto errout;
}
ret = imx9_readmii(priv, GMII_RTL8211F_MIICR1_D08, &reg);
if (ret < 0)
{
nerr("ERROR: Reading MIICR1, imx9_readmii failed: %d\n", ret);
goto errout;
}
#ifdef CONFIG_IMX9_ENET1_RGMII_ID
reg |= GMII_RTL8211F_MIICR1_TX_DELAY;
#else
reg &= ~GMII_RTL8211F_MIICR1_TX_DELAY;
#endif
ret = imx9_writemii(priv, GMII_RTL8211F_MIICR1_D08, reg);
if (ret < 0)
{
nerr("ERROR: Enabling TXDLY, imx9_writemii failed: %d\n", ret);
goto errout;
}
ret = imx9_readmii(priv, GMII_RTL8211F_MIICR2_D08, &reg);
if (ret < 0)
{
nerr("ERROR: Reading MIICR2, imx9_readmii failed: %d\n", ret);
goto errout;
}
#ifdef CONFIG_IMX9_ENET1_RGMII_ID
reg |= GMII_RTL8211F_MIICR2_RX_DELAY;
#else
reg &= ~GMII_RTL8211F_MIICR2_RX_DELAY;
#endif
ret = imx9_writemii(priv, GMII_RTL8211F_MIICR2_D08, reg);
if (ret < 0)
{
nerr("ERROR: Enabling RXDLY, imx9_writemii failed: %d\n", ret);
goto errout;
}
ret = imx9_writemii(priv, GMII_RTL8211F_PAGSR, prev_page);
if (ret < 0)
{
nerr("ERROR: Restoring page, imx9_writemii failed: %d\n", ret);
goto errout;
}
errout:
return ret;
}
#endif /* CONFIG_IMX9_ENET1_RGMII */
/****************************************************************************
* Function: imx9_initphy
*
@ -2897,6 +2998,17 @@ static inline int imx9_initphy(struct imx9_driver_s *priv, bool renogphy)
imx9_enet_putreg32(priv, rcr, IMX9_ENET_RCR_OFFSET);
imx9_enet_putreg32(priv, tcr, IMX9_ENET_TCR_OFFSET);
if (priv->phy_type == PHY_RGMII)
{
ret = imx9_config_rgmii_id(priv);
if (ret < 0)
{
nerr("ERROR: configure internal delay failed: %d\n", ret);
return ret;
}
}
return OK;
}

View file

@ -68,6 +68,7 @@ CONFIG_IMX9_DMA_ALLOC=y
CONFIG_IMX9_DMA_ALLOC_POOL_SIZE=81920
CONFIG_IMX9_EDMA=y
CONFIG_IMX9_ENET1_RGMII=y
CONFIG_IMX9_ENET1_RGMII_ID=y
CONFIG_IMX9_ENET=y
CONFIG_IMX9_ENET_USE_OTP_MAC=y
CONFIG_IMX9_FLEXIO1_PWM=y

View file

@ -73,6 +73,7 @@ CONFIG_IMX9_DMA_ALLOC=y
CONFIG_IMX9_DMA_ALLOC_POOL_SIZE=81920
CONFIG_IMX9_EDMA=y
CONFIG_IMX9_ENET1_RGMII=y
CONFIG_IMX9_ENET1_RGMII_ID=y
CONFIG_IMX9_ENET=y
CONFIG_IMX9_ENET_USE_OTP_MAC=y
CONFIG_IMX9_FLEXIO1_PWM=y

View file

@ -46,6 +46,7 @@ CONFIG_IMX9_DMA_ALLOC=y
CONFIG_IMX9_DMA_ALLOC_POOL_SIZE=81920
CONFIG_IMX9_EDMA=y
CONFIG_IMX9_ENET1_RGMII=y
CONFIG_IMX9_ENET1_RGMII_ID=y
CONFIG_IMX9_ENET=y
CONFIG_IMX9_ENET_USE_OTP_MAC=y
CONFIG_IMX9_FLEXIO1_PWM=y

View file

@ -94,7 +94,8 @@
#define GMII_RTL8211F_PHYSCR_A46 20 /* PHY Special Config Register */
#define GMII_RTL8211F_LCR_D04 16 /* LED Control Register */
#define GMII_RTL8211F_EEELCR_D04 17 /* EEE LED Control Register */
#define GMII_RTL8211F_MIICR_D08 21 /* MII Control Register */
#define GMII_RTL8211F_MIICR1_D08 17 /* MII Control Register 1 */
#define GMII_RTL8211F_MIICR2_D08 21 /* MII Control Register 2 */
#define GMII_RTL8211F_INTBCR_D40 22 /* INTB Pin Control Register */
/* MII register bit settings ************************************************/
@ -308,6 +309,8 @@
#define GMII_RTL8211F_PHYSR_100MBPS 0x10
#define GMII_RTL8211F_PHYSR_1000MBPS 0x20
#define GMII_RTL8211F_PHYSR_DUPLEX 0x8
#define GMII_RTL8211F_MIICR1_TX_DELAY (1 << 8) /* Enable PHY internal TX delay */
#define GMII_RTL8211F_MIICR2_RX_DELAY (1 << 3) /* Enable PHY internal RX delay */
/****************************************************************************
* Type Definitions