diff --git a/arch/arm/src/imxrt/imxrt_enet.c b/arch/arm/src/imxrt/imxrt_enet.c index df8a72489c8..bd70a5ac28b 100644 --- a/arch/arm/src/imxrt/imxrt_enet.c +++ b/arch/arm/src/imxrt/imxrt_enet.c @@ -250,8 +250,25 @@ * ...and further PHY descriptions here. */ -#if defined(CONFIG_ETH0_PHY_KSZ8081) -# define BOARD_PHY_NAME "KSZ8081" +#if defined(CONFIG_ETH0_PHY_MULTI) +# if !defined(BOARD_ETH0_PHY_LIST) +# error "CONFIG_ETH0_PHY_MULTI requires board.h to define BOARD_ETH0_PHY_LIST!" +# endif +# define BOARD_PHY_NAME g_board_phys[priv->current_phy].name +# define BOARD_PHYID1 g_board_phys[priv->current_phy].id1 +# define BOARD_PHYID2 g_board_phys[priv->current_phy].id2 +# define BOARD_PHY_STATUS g_board_phys[priv->current_phy].status +# define BOARD_PHY_ADDR priv->current_phy_address +# define BOARD_PHY_10BASET(s) (imxrt_phy_status(priv, (s), g_board_phys[priv->current_phy].mbps10) != 0) +# define BOARD_PHY_100BASET(s) (imxrt_phy_status(priv, (s), g_board_phys[priv->current_phy].mbps100) != 0) +# define BOARD_PHY_ISDUPLEX(s) (imxrt_phy_status(priv, (s), g_board_phys[priv->current_phy].duplex) != 0) +# define BOARD_PHY_ISCLAUSE45() (g_board_phys[priv->current_phy].clause == 45) +# define CLAUSE45 +# define MMD1 1 +# define MMD1_PMA_STATUS1 1 +# define MMD1_PS1_RECEIVE_LINK_STATUS (1 << 2) +#elif defined(CONFIG_ETH0_PHY_KSZ8081) +# define BOARD_PHY_NAME MII_KSZ8081_NAME # define BOARD_PHYID1 MII_PHYID1_KSZ8081 # define BOARD_PHYID2 MII_PHYID2_KSZ8081 # define BOARD_PHY_STATUS MII_KSZ8081_PHYCTRL1 @@ -260,7 +277,7 @@ # define BOARD_PHY_100BASET(s) (((s) & MII_PHYCTRL1_MODE_100HDX) != 0) # define BOARD_PHY_ISDUPLEX(s) (((s) & MII_PHYCTRL1_MODE_DUPLEX) != 0) #elif defined(CONFIG_ETH0_PHY_LAN8720) -# define BOARD_PHY_NAME "LAN8720" +# define BOARD_PHY_NAME MII_LAN8720_NAME # define BOARD_PHYID1 MII_PHYID1_LAN8720 # define BOARD_PHYID2 MII_PHYID2_LAN8720 # define BOARD_PHY_STATUS MII_LAN8720_SCSR @@ -269,7 +286,7 @@ # define BOARD_PHY_100BASET(s) (((s)&MII_LAN8720_SPSCR_100MBPS) != 0) # define BOARD_PHY_ISDUPLEX(s) (((s)&MII_LAN8720_SPSCR_DUPLEX) != 0) #elif defined(CONFIG_ETH0_PHY_LAN8742A) -# define BOARD_PHY_NAME "LAN8742A" +# define BOARD_PHY_NAME MII_LAN8742A_NAME # define BOARD_PHYID1 MII_PHYID1_LAN8742A # define BOARD_PHYID2 MII_PHYID2_LAN8742A # define BOARD_PHY_STATUS MII_LAN8740_SCSR @@ -278,7 +295,7 @@ # define BOARD_PHY_100BASET(s) (((s)&MII_LAN8720_SPSCR_100MBPS) != 0) # define BOARD_PHY_ISDUPLEX(s) (((s)&MII_LAN8720_SPSCR_DUPLEX) != 0) #elif defined(CONFIG_ETH0_PHY_DP83825I) -# define BOARD_PHY_NAME "DP83825I" +# define BOARD_PHY_NAME MII_DP83825I_NAME # define BOARD_PHYID1 MII_PHYID1_DP83825I # define BOARD_PHYID2 MII_PHYID2_DP83825I # define BOARD_PHY_STATUS MII_DP83825I_PHYSTS @@ -287,7 +304,7 @@ # define BOARD_PHY_100BASET(s) (((s) & MII_DP83825I_PHYSTS_SPEED) == 0) # define BOARD_PHY_ISDUPLEX(s) (((s) & MII_DP83825I_PHYSTS_DUPLEX) != 0) #elif defined(CONFIG_ETH0_PHY_TJA1103) -# define BOARD_PHY_NAME "TJA1103" +# define BOARD_PHY_NAME MII_TJA1103_NAME # define BOARD_PHYID1 MII_PHYID1_TJA1103 # define BOARD_PHYID2 MII_PHYID2_TJA1103 # define BOARD_PHY_STATUS MII_TJA110X_BSR @@ -300,7 +317,7 @@ # define MMD1_PMA_STATUS1 1 # define MMD1_PS1_RECEIVE_LINK_STATUS (1 << 2) #elif defined(CONFIG_ETH0_PHY_YT8512) -# define BOARD_PHY_NAME "YT8512" +# define BOARD_PHY_NAME MII_YT8512_NAME # define BOARD_PHYID1 MII_PHYID1_YT8512 # define BOARD_PHYID2 MII_PHYID2_YT8512 # define BOARD_PHY_STATUS MII_YT8512_PHYSTS @@ -375,6 +392,10 @@ struct imxrt_driver_s struct enet_desc_s *txdesc; /* A pointer to the list of TX descriptor */ struct enet_desc_s *rxdesc; /* A pointer to the list of RX descriptors */ +#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 /* This holds the information visible to the NuttX network */ struct net_driver_s dev; /* Interface understood by the network */ @@ -384,6 +405,15 @@ struct imxrt_driver_s * Private Data ****************************************************************************/ +/* BOARD_ETH0_PHY_LIST provided by the board.h for CONFIG_ETH0_PHY_MULTI */ + +#if defined(CONFIG_ETH0_PHY_MULTI) +const struct phy_desc_s g_board_phys[] = + { + BOARD_ETH0_PHY_LIST + }; +#endif + static struct imxrt_driver_s g_enet[CONFIG_IMXRT_ENET_NETHIFS]; /* The DMA descriptors */ @@ -470,6 +500,13 @@ static int imxrt_ioctl(struct net_driver_s *dev, int cmd, /* PHY/MII support */ +#if defined(CONFIG_ETH0_PHY_MULTI) +static int imxrt_phy_is(struct imxrt_driver_s *priv, const char *name); +static int imxrt_phy_status(struct imxrt_driver_s *priv, int phydata, + uint16_t mask); +static int imxrt_determine_phy(struct imxrt_driver_s *priv); +#endif + #if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) static int imxrt_phyintenable(struct imxrt_driver_s *priv); #endif @@ -1377,6 +1414,15 @@ static int imxrt_ifup_action(struct net_driver_s *dev, bool resetphy) /* Configure the PHY */ +#if defined(CONFIG_ETH0_PHY_MULTI) + ret = imxrt_determine_phy(priv); + if (ret < 0) + { + nerr("ERROR: Failed to determine the PHY: %d\n", ret); + return ret; + } +#endif + ret = imxrt_initphy(priv, resetphy); if (ret < 0) { @@ -1872,7 +1918,11 @@ 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); #if defined(CLAUSE45) - if (MII_MSR == req->reg_num) + if ( +# if defined(CONFIG_ETH0_PHY_MULTI) + BOARD_PHY_ISCLAUSE45() && +# endif + MII_MSR == req->reg_num) { ret = imxrt_readmmd(priv, req->phy_id, MMD1, MMD1_PMA_STATUS1, &req->val_out); @@ -1926,46 +1976,60 @@ static int imxrt_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) #if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) static int imxrt_phyintenable(struct imxrt_driver_s *priv) { +#if defined(CONFIG_ETH0_PHY_KSZ8051) || defined(CONFIG_ETH0_PHY_KSZ8061) || \ + defined(CONFIG_ETH0_PHY_KSZ8081) || defined(CONFIG_ETH0_PHY_DP83825I) || \ + defined(CONFIG_ETH0_YT8512) || defined(CONFIG_ETH0_PHY_MULTI) + uint16_t phyval; int ret; -#if defined(CONFIG_ETH0_PHY_KSZ8051) || defined(CONFIG_ETH0_PHY_KSZ8061) || \ - defined(CONFIG_ETH0_PHY_KSZ8081) || defined(CONFIG_ETH0_PHY_DP83825I) + /* Compile time Kzxxxx defaults */ - /* Read the interrupt status register in order to clear any pending - * interrupts - */ + uint16_t mask = MII_KSZ80X1_INT_LDEN | MII_KSZ80X1_INT_LUEN; + uint8_t rreg = MII_KSZ8081_INT; + uint8_t wreg = rreg; - ret = imxrt_readmii(priv, priv->phyaddr, MII_KSZ8081_INT, &phyval); - if (ret == OK) + /* Compile time YT8512 defaults */ +# if defined(CONFIG_ETH0_YT8512) + mask = MII_YT8512_IMR_LD_EN | MII_YT8512_IMR_LU_EN; + rreg = MII_YT8512_ISR; + wreg = MII_YT8512_IMR; +# endif + + /* Run time YT8512 defaults */ +# if defined(CONFIG_ETH0_PHY_MULTI) + if (imxrt_phy_is(priv, MII_YT8512_NAME)) { - /* Enable link up/down interrupts */ - - ret = imxrt_writemii(priv, priv->phyaddr, MII_KSZ8081_INT, - (MII_KSZ80X1_INT_LDEN | MII_KSZ80X1_INT_LUEN)); + mask = MII_YT8512_IMR_LD_EN | MII_YT8512_IMR_LU_EN; + rreg = MII_YT8512_ISR; + wreg = MII_YT8512_IMR; } - - return ret; -#elif defined(CONFIG_ETH0_YT8512) + else if (!(imxrt_phy_is(priv, MII_KSZ8051_NAME) || + imxrt_phy_is(priv, MII_KSZ8061_NAME) || + imxrt_phy_is(priv, MII_KSZ8081_NAME) || + imxrt_phy_is(priv, MII_DP83825I_NAME))) + { + return -ENOSYS; + } +# endif /* Read the interrupt status register in order to clear any pending * interrupts */ - ret = imxrt_readmii(priv, priv->phyaddr, MII_YT8512_ISR, &phyval); + ret = imxrt_readmii(priv, priv->phyaddr, rreg, &phyval); if (ret == OK) { /* Enable link up/down interrupts */ - ret = imxrt_writemii(priv, priv->phyaddr, MII_YT8512_IMR, - (MII_YT8512_IMR_LD_EN | MII_YT8512_IMR_LU_EN)); + ret = imxrt_writemii(priv, priv->phyaddr, wreg, mask); } return ret; #else # error Unrecognized PHY return -ENOSYS; -#endif +# endif } #endif @@ -2121,6 +2185,126 @@ static int imxrt_readmii(struct imxrt_driver_s *priv, uint8_t phyaddr, return OK; } +#if defined(CONFIG_ETH0_PHY_MULTI) +/**************************************************************************** + * Function: imxrt_determine_phy + * + * Description: + * Uses the board.h supplied PHY list to determine which PHY + * is populated on this board. + * + * Input Parameters: + * priv - Reference to the private ENET driver state structure + * + * Returned Value: + * Zero on success, a -ENOENT errno value on failure. + * + ****************************************************************************/ + +static int imxrt_determine_phy(struct imxrt_driver_s *priv) +{ + uint16_t phydata = 0xffff; + uint8_t phyaddr = 0; + uint8_t last_phyaddr = 0; + int retries; + int ret; + + for (priv->current_phy = 0; priv->current_phy < nitems(g_board_phys); + priv->current_phy++) + { + priv->current_phy_address = + (uint8_t) g_board_phys[priv->current_phy].address_lo; + last_phyaddr = g_board_phys[priv->current_phy].address_high == 0xffff ? + priv->current_phy_address : + (uint8_t) g_board_phys[priv->current_phy].address_high; + + for (phyaddr = priv->current_phy_address; phyaddr <= last_phyaddr; + phyaddr++) + { + retries = 0; + do + { + nxsig_usleep(100); + phydata = 0xffff; + ret = imxrt_readmii(priv, phyaddr, MII_PHYID1, &phydata); + } + while ((ret < 0 || phydata == 0xffff) && ++retries < 3); + + if (retries <= 3 && ret == 0 && + phydata == g_board_phys[priv->current_phy].id1) + { + do + { + nxsig_usleep(100); + phydata = 0xffff; + ret = imxrt_readmii(priv, phyaddr, MII_PHYID2, &phydata); + } + while ((ret < 0 || phydata == 0xffff) && ++retries < 3); + if (retries <= 3 && ret == 0 && + (phydata & 0xfff0) == + (g_board_phys[priv->current_phy].id2 & 0xfff0)) + { + return OK; + } + } + } + } + + return -ENOENT; +} + +/**************************************************************************** + * Function: imxrt_phy_is + * + * Description: + * Compares the name with the current selected PHY's name + * + * Input Parameters: + * priv - Reference to the private ENET driver state structure + * name - a pointer to comapre to. + * + * Returned Value: + * 1 on match, a 0 on no match. + * + ****************************************************************************/ + +static int imxrt_phy_is(struct imxrt_driver_s *priv, const char *name) +{ + return strcmp(g_board_phys[priv->current_phy].name, name) == 0; +} + +/**************************************************************************** + * Function: imxrt_phy_status + * + * Description: + * Compares the name with the current selected PHY's name. + * + * Input Parameters: + * priv - Reference to the private ENET driver state structure + * phydata - last read phy data - may be ignored if there is no + * status register defined by the current PHY. + * mask - A value to and with phydata if a status register is + * defined. Or the value retunred if no status register is + * defined. + * + * Returned Value: + * mask or (phydat & mask) + * + ****************************************************************************/ + +static int imxrt_phy_status(struct imxrt_driver_s *priv, int phydata, + uint16_t mask) +{ + int rv = mask; + if (g_board_phys[priv->current_phy].status != 0xffff) + { + rv &= phydata; + } + + return rv; +} +#endif + #if 0 #if defined(CLAUSE45) /**************************************************************************** @@ -2416,213 +2600,265 @@ static inline int imxrt_initphy(struct imxrt_driver_s *priv, bool renogphy) return -ENXIO; } -#ifdef CONFIG_ETH0_PHY_KSZ8081 - /* Reset PHY */ - - imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); - - /* Set RMII mode */ - - ret = imxrt_readmii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, &phydata); - if (ret < 0) +#if defined(CONFIG_ETH0_PHY_KSZ8081) || defined(CONFIG_ETH0_PHY_MULTI) +# if defined(CONFIG_ETH0_PHY_MULTI) + if (imxrt_phy_is(priv, MII_KSZ8081_NAME)) { - nerr("ERROR: Failed to read MII_KSZ8081_PHYCTRL2\n"); - return ret; - } +# endif + /* Reset PHY */ - /* Indicate 50MHz clock */ + imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); - imxrt_writemii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, - (phydata | (1 << 7))); + /* Set RMII mode */ - /* Switch off NAND Tree mode (in case it was set via pinning) */ - - ret = imxrt_readmii(priv, phyaddr, MII_KSZ8081_OMSO, &phydata); - if (ret < 0) - { - nerr("ERROR: Failed to read MII_KSZ8081_OMSO: %d\n", ret); - return ret; - } - - imxrt_writemii(priv, phyaddr, MII_KSZ8081_OMSO, - (phydata & ~(1 << 5))); - - /* Set Ethernet led to green = activity and yellow = link and */ - - ret = imxrt_readmii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, &phydata); - if (ret < 0) - { - nerr("ERROR: Failed to read MII_KSZ8081_PHYCTRL2\n"); - return ret; - } - - imxrt_writemii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, - (phydata | (1 << 4))); - - imxrt_writemii(priv, phyaddr, MII_ADVERTISE, - MII_ADVERTISE_100BASETXFULL | - MII_ADVERTISE_100BASETXHALF | - MII_ADVERTISE_10BASETXFULL | - MII_ADVERTISE_10BASETXHALF | - MII_ADVERTISE_CSMA); - -#elif defined (CONFIG_ETH0_PHY_LAN8720) || defined (CONFIG_ETH0_PHY_LAN8742A) - /* Make sure that PHY comes up in correct mode when it's reset */ - - imxrt_writemii(priv, phyaddr, MII_LAN8720_MODES, - MII_LAN8720_MODES_RESV | MII_LAN8720_MODES_ALL | - MII_LAN8720_MODES_PHYAD(BOARD_PHY_ADDR)); - - /* ...and reset PHY */ - - imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); - -#elif defined (CONFIG_ETH0_PHY_DP83825I) - - /* Reset PHY */ - - imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); - - /* Set RMII mode and Indicate 50MHz clock */ - - imxrt_writemii(priv, phyaddr, MII_DP83825I_RCSR, - MII_DP83825I_RCSC_ELAST_2 | MII_DP83825I_RCSC_RMIICS); - - imxrt_writemii(priv, phyaddr, MII_ADVERTISE, - MII_ADVERTISE_100BASETXFULL | - MII_ADVERTISE_100BASETXHALF | - MII_ADVERTISE_10BASETXFULL | - MII_ADVERTISE_10BASETXHALF | - MII_ADVERTISE_CSMA); - -#elif defined (CONFIG_ETH0_PHY_YT8512) - - /* Reset PHY */ - - imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); - - /* Config LEDs */ - - imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, - MII_YT8512_LED0); - - imxrt_readmii(priv, phyaddr, MII_YT8512_DEBUG_DATA, &phydata); - - imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, - MII_YT8512_LED0); - - imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_DATA, 0x331); - - imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, - MII_YT8512_LED1); - - imxrt_readmii(priv, phyaddr, MII_YT8512_DEBUG_DATA, &phydata); - - imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, - MII_YT8512_LED1); - - imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_DATA, 0x30); - - /* Set negotiation */ - - imxrt_writemii(priv, phyaddr, MII_ADVERTISE, - MII_ADVERTISE_100BASETXFULL | - MII_ADVERTISE_100BASETXHALF | - MII_ADVERTISE_10BASETXFULL | - MII_ADVERTISE_10BASETXHALF | - MII_ADVERTISE_CSMA); - -#endif -#if !defined(CONFIG_ETH0_PHY_TJA1103) - - /* Start auto negotiation */ - - ninfo("%s: Start Autonegotiation...\n", BOARD_PHY_NAME); - imxrt_writemii(priv, phyaddr, MII_MCR, - (MII_MCR_ANRESTART | MII_MCR_ANENABLE)); - - /* Wait for auto negotiation to complete */ - - for (retries = 0; retries < LINK_NLOOPS; retries++) - { - ret = imxrt_readmii(priv, phyaddr, MII_MSR, &phydata); + ret = imxrt_readmii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, &phydata); if (ret < 0) { - nerr("ERROR: Failed to read %s MII_MSR: %d\n", - BOARD_PHY_NAME, ret); + nerr("ERROR: Failed to read MII_KSZ8081_PHYCTRL2\n"); return ret; } + /* Indicate 50MHz clock */ + + imxrt_writemii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, + (phydata | (1 << 7))); + + /* Switch off NAND Tree mode (in case it was set via pinning) */ + + ret = imxrt_readmii(priv, phyaddr, MII_KSZ8081_OMSO, &phydata); + if (ret < 0) + { + nerr("ERROR: Failed to read MII_KSZ8081_OMSO: %d\n", ret); + return ret; + } + + imxrt_writemii(priv, phyaddr, MII_KSZ8081_OMSO, + (phydata & ~(1 << 5))); + + /* Set Ethernet led to green = activity and yellow = link and */ + + ret = imxrt_readmii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, &phydata); + if (ret < 0) + { + nerr("ERROR: Failed to read MII_KSZ8081_PHYCTRL2\n"); + return ret; + } + + imxrt_writemii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, + (phydata | (1 << 4))); + + imxrt_writemii(priv, phyaddr, MII_ADVERTISE, + MII_ADVERTISE_100BASETXFULL | + MII_ADVERTISE_100BASETXHALF | + MII_ADVERTISE_10BASETXFULL | + MII_ADVERTISE_10BASETXHALF | + MII_ADVERTISE_CSMA); +# if defined(CONFIG_ETH0_PHY_MULTI) + } + +# endif +#endif +#if defined (CONFIG_ETH0_PHY_LAN8720) || \ + defined (CONFIG_ETH0_PHY_LAN8742A) || \ + defined (CONFIG_ETH0_PHY_MULTI) + +# if defined(CONFIG_ETH0_PHY_MULTI) + if (imxrt_phy_is(priv, MII_LAN8720_NAME) || + imxrt_phy_is(priv, MII_LAN8742A_NAME)) + { +# endif + + /* Make sure that PHY comes up in correct mode when it's reset */ + + imxrt_writemii(priv, phyaddr, MII_LAN8720_MODES, + MII_LAN8720_MODES_RESV | MII_LAN8720_MODES_ALL | + MII_LAN8720_MODES_PHYAD(BOARD_PHY_ADDR)); + + /* ...and reset PHY */ + + imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); + +# if defined(CONFIG_ETH0_PHY_MULTI) + } +# endif +#endif +#if defined (CONFIG_ETH0_PHY_DP83825I) || defined (CONFIG_ETH0_PHY_MULTI) + +#if defined(CONFIG_ETH0_PHY_MULTI) + if (imxrt_phy_is(priv, MII_DP83825I_NAME)) + { +#endif + + /* Reset PHY */ + + imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); + + /* Set RMII mode and Indicate 50MHz clock */ + + imxrt_writemii(priv, phyaddr, MII_DP83825I_RCSR, + MII_DP83825I_RCSC_ELAST_2 | + MII_DP83825I_RCSC_RMIICS); + + imxrt_writemii(priv, phyaddr, MII_ADVERTISE, + MII_ADVERTISE_100BASETXFULL | + MII_ADVERTISE_100BASETXHALF | + MII_ADVERTISE_10BASETXFULL | + MII_ADVERTISE_10BASETXHALF | + MII_ADVERTISE_CSMA); + +# if defined(CONFIG_ETH0_PHY_MULTI) + } +# endif +#endif + +#if defined(CONFIG_ETH0_PHY_YT8512) || defined(CONFIG_ETH0_PHY_MULTI) +# if defined(CONFIG_ETH0_PHY_MULTI) + if (!imxrt_phy_is(priv, MII_YT8512_NAME)) + { +# endif + /* Reset PHY */ + + imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); + + /* Config LEDs */ + + imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, + MII_YT8512_LED0); + + imxrt_readmii(priv, phyaddr, MII_YT8512_DEBUG_DATA, &phydata); + + imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, + MII_YT8512_LED0); + + imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_DATA, 0x331); + + imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, + MII_YT8512_LED1); + + imxrt_readmii(priv, phyaddr, MII_YT8512_DEBUG_DATA, &phydata); + + imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, + MII_YT8512_LED1); + + imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_DATA, 0x30); + + /* Set negotiation */ + + imxrt_writemii(priv, phyaddr, MII_ADVERTISE, + MII_ADVERTISE_100BASETXFULL | + MII_ADVERTISE_100BASETXHALF | + MII_ADVERTISE_10BASETXFULL | + MII_ADVERTISE_10BASETXHALF | + MII_ADVERTISE_CSMA); + +# if defined(CONFIG_ETH0_PHY_MULTI) + } +# endif +#endif + +#if !defined(CONFIG_ETH0_PHY_TJA1103) +#if defined(CONFIG_ETH0_PHY_MULTI) + if (!imxrt_phy_is(priv, MII_TJA1103_NAME)) + { +#endif + /* Start auto negotiation */ + + ninfo("%s: Start Autonegotiation...\n", BOARD_PHY_NAME); + imxrt_writemii(priv, phyaddr, MII_MCR, + (MII_MCR_ANRESTART | MII_MCR_ANENABLE)); + + /* Wait for auto negotiation to complete */ + + for (retries = 0; retries < LINK_NLOOPS; retries++) + { + ret = imxrt_readmii(priv, phyaddr, MII_MSR, &phydata); + if (ret < 0) + { + nerr("ERROR: Failed to read %s MII_MSR: %d\n", + BOARD_PHY_NAME, ret); + return ret; + } + + if (phydata & MII_MSR_ANEGCOMPLETE) + { + break; + } + + nxsig_usleep(LINK_WAITUS); + } + if (phydata & MII_MSR_ANEGCOMPLETE) { - break; + ninfo("%s: Autonegotiation complete\n", BOARD_PHY_NAME); + ninfo("%s: MII_MSR: %04x\n", BOARD_PHY_NAME, phydata); } + else + { + /* TODO: Autonegotiation has right now failed. Maybe the Eth + * cable is not connected. PHY chip have mechanisms to + * configure link OK. We should leave autconf on, and find a + * way to re-configure MCU whenever the link is ready. + */ - nxsig_usleep(LINK_WAITUS); - } - - if (phydata & MII_MSR_ANEGCOMPLETE) - { - ninfo("%s: Autonegotiation complete\n", BOARD_PHY_NAME); - ninfo("%s: MII_MSR: %04x\n", BOARD_PHY_NAME, phydata); - } - else - { - /* TODO: Autonegotiation has right now failed. Maybe the Eth cable - * is not connected. PHY chip have mechanisms to configure link - * OK. We should leave autconf on, and find a way to re-configure - * MCU whenever the link is ready. - */ - - ninfo("%s: Autonegotiation failed [%d] (is cable plugged-in ?), " - "default to 10Mbs mode\n", \ - BOARD_PHY_NAME, retries); - - /* Stop auto negotiation */ - - imxrt_writemii(priv, phyaddr, MII_MCR, 0); + ninfo("%s: Autonegotiation failed [%d] (is cable plugged-in ?)" + ", default to 10Mbs mode\n", + BOARD_PHY_NAME, retries); + + /* Stop auto negotiation */ + + imxrt_writemii(priv, phyaddr, MII_MCR, 0); + } +# if defined(CONFIG_ETH0_PHY_MULTI) } +# endif #endif } #if !defined(CONFIG_ETH0_PHY_TJA1103) - /* When we get here we have a (negotiated) speed and duplex. This is also - * the point we enter if renegotiation is turned off, so have multiple - * attempts at reading the status register in case the PHY isn't awake - * properly. - */ - - retries = 0; - do +# if defined(CONFIG_ETH0_PHY_MULTI) + if (!imxrt_phy_is(priv, MII_TJA1103_NAME)) { - phydata = 0xffff; - ret = imxrt_readmii(priv, phyaddr, BOARD_PHY_STATUS, &phydata); - } - while ((ret < 0 || phydata == 0xffff) && ++retries < 3); +# endif + /* When we get here we have a (negotiated) speed and duplex. This + * is also the point we enter if renegotiation is turned off, so have + * multiple attempts at reading the status register in case the PHY + * isn't awake properly. + */ - /* If we didn't successfully read anything and we haven't tried a physical - * renegotiation then lets do that - */ - - if (retries >= 3) - { - if (renogphy == false) + retries = 0; + do { - /* Give things one more chance with renegotiation turned on */ - - return imxrt_initphy(priv, true); + phydata = 0xffff; + ret = imxrt_readmii(priv, phyaddr, BOARD_PHY_STATUS, &phydata); } - else + while ((ret < 0 || phydata == 0xffff) && ++retries < 3); + + /* If we didn't successfully read anything and we haven't tried + * a physical renegotiation then lets do that + */ + + if (retries >= 3) { - /* That didn't end well, just give up */ + if (renogphy == false) + { + /* Give things one more chance with renegotiation turned on */ - nerr("ERROR: Failed to read %s BOARD_PHY_STATUS[%02x]: %d\n", - BOARD_PHY_NAME, BOARD_PHY_STATUS, ret); - return ret; + return imxrt_initphy(priv, true); + } + else + { + /* That didn't end well, just give up */ + + nerr("ERROR: Failed to read %s BOARD_PHY_STATUS[%02x]: %d\n", + BOARD_PHY_NAME, BOARD_PHY_STATUS, ret); + return ret; + } } - } - ninfo("%s: BOARD_PHY_STATUS: %04x\n", BOARD_PHY_NAME, phydata); + ninfo("%s: BOARD_PHY_STATUS: %04x\n", BOARD_PHY_NAME, phydata); +# if defined(CONFIG_ETH0_PHY_MULTI) + } +# endif #endif /* Set up the transmit and receive control registers based on the