diff --git a/arch/arm64/src/imx9/Kconfig b/arch/arm64/src/imx9/Kconfig index ee0dd1627fe..79dcafad166 100644 --- a/arch/arm64/src/imx9/Kconfig +++ b/arch/arm64/src/imx9/Kconfig @@ -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 diff --git a/arch/arm64/src/imx9/imx9_enet.c b/arch/arm64/src/imx9/imx9_enet.c index f79663e9b7f..6a10d12fd0a 100644 --- a/arch/arm64/src/imx9/imx9_enet.c +++ b/arch/arm64/src/imx9/imx9_enet.c @@ -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, ®); + 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, ®); + 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; } diff --git a/boards/arm64/imx9/imx93-evk/configs/knsh/defconfig b/boards/arm64/imx9/imx93-evk/configs/knsh/defconfig index cb66d1c7719..e44ea00775b 100644 --- a/boards/arm64/imx9/imx93-evk/configs/knsh/defconfig +++ b/boards/arm64/imx9/imx93-evk/configs/knsh/defconfig @@ -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 diff --git a/boards/arm64/imx9/imx93-evk/configs/koptee/defconfig b/boards/arm64/imx9/imx93-evk/configs/koptee/defconfig index 375110df100..ef92227dee6 100644 --- a/boards/arm64/imx9/imx93-evk/configs/koptee/defconfig +++ b/boards/arm64/imx9/imx93-evk/configs/koptee/defconfig @@ -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 diff --git a/boards/arm64/imx9/imx93-evk/configs/nsh/defconfig b/boards/arm64/imx9/imx93-evk/configs/nsh/defconfig index 6ed1e18226c..09f153f038c 100644 --- a/boards/arm64/imx9/imx93-evk/configs/nsh/defconfig +++ b/boards/arm64/imx9/imx93-evk/configs/nsh/defconfig @@ -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 diff --git a/include/nuttx/net/gmii.h b/include/nuttx/net/gmii.h index 184af407833..f4be7bb5bbb 100644 --- a/include/nuttx/net/gmii.h +++ b/include/nuttx/net/gmii.h @@ -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