From fb6bef2c2d768dfee37efd4bff75cff49f38d727 Mon Sep 17 00:00:00 2001 From: Masayuki Ishikawa Date: Mon, 17 Apr 2023 10:47:39 +0900 Subject: [PATCH] arch: imx6: Add support for AR8031 gigabit ethernet phy Summary: - This commit adds AR8031 gigabit ethernet phy for the sabre-6quad board. Impact: - None Testing: - Tested with sabre-6quad:netnsh_ar8031 (will be added later) Signed-off-by: Masayuki Ishikawa --- arch/arm/src/imx6/Kconfig | 4 ++ arch/arm/src/imx6/hardware/imx_enet.h | 5 +- arch/arm/src/imx6/imx_enet.c | 75 ++++++++++++++++++++------- 3 files changed, 63 insertions(+), 21 deletions(-) diff --git a/arch/arm/src/imx6/Kconfig b/arch/arm/src/imx6/Kconfig index 82844c4045..6692a25c6a 100644 --- a/arch/arm/src/imx6/Kconfig +++ b/arch/arm/src/imx6/Kconfig @@ -165,6 +165,10 @@ config IMX_ENET_PHYINIT imx_phy_boardinitialize(); The i.MX6 ENET driver will call this function one time before it first uses the PHY. +config IMX_ENET_WITH_QEMU + bool "With QEMU" + default y + endmenu # IMX_ENET config IMX_DDR_SIZE diff --git a/arch/arm/src/imx6/hardware/imx_enet.h b/arch/arm/src/imx6/hardware/imx_enet.h index 1f58533ff3..1f38f1a666 100644 --- a/arch/arm/src/imx6/hardware/imx_enet.h +++ b/arch/arm/src/imx6/hardware/imx_enet.h @@ -191,7 +191,7 @@ #define ENET_ECR_MAGICEN (1 << 2) /* Bit 2: Magic packet detection enable */ #define ENET_ECR_SLEEP (1 << 3) /* Bit 3: Sleep mode enable */ #define ENET_ECR_EN1588 (1 << 4) /* Bit 4: EN1588 enable */ - /* Bit 5: Reserved */ +#define ENET_ECR_SPEED (1 << 5) /* Bit 5: 1000-Mbit/s mode */ #define ENET_ECR_DBGEN (1 << 6) /* Bit 6: Debug enable */ #define ENET_ECR_STOPEN (1 << 7) /* Bit 7: STOPEN Signal Control */ #ifdef IMX_ENET_HAS_DBSWAP @@ -248,7 +248,8 @@ #define ENET_RCR_PROM (1 << 3) /* Bit 3: Promiscuous mode */ #define ENET_RCR_BC_REJ (1 << 4) /* Bit 4: Broadcast frame reject */ #define ENET_RCR_FCE (1 << 5) /* Bit 5: Flow control enable */ - /* Bits 6-7: Reserved */ +#define ENET_RCR_RGMII_EN (1 << 6) /* Bit 6: RGMII mode enable */ + /* Bit 7: Reserved */ #define ENET_RCR_RMII_MODE (1 << 8) /* Bit 8: RMII mode enable */ #define ENET_RCR_RMII_10T (1 << 9) /* Bit 9: Enables 10-Mbps mode of the RMII */ /* Bits 10-11: Reserved */ diff --git a/arch/arm/src/imx6/imx_enet.c b/arch/arm/src/imx6/imx_enet.c index f22176dc3b..f61aa7b7aa 100644 --- a/arch/arm/src/imx6/imx_enet.c +++ b/arch/arm/src/imx6/imx_enet.c @@ -201,6 +201,16 @@ # define BOARD_PHY_10BASET(s) (((s) & MII_DP83825I_PHYSTS_SPEED) != 0) # 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_AR8031) +# define BOARD_PHY_NAME "AR8031" +# define BOARD_PHYID1 MII_PHYID1_AR8031 +# define BOARD_PHYID2 MII_PHYID2_AR8031 +# define BOARD_PHY_STATUS MII_AR8031_PSSR +# define BOARD_PHY_ADDR (1) +# define BOARD_PHY_10BASET(s) (((s) & MII_AR8031_PSSR_10MBPS) == ((s) & MII_AR8031_PSSR_SPEEDMASK)) +# define BOARD_PHY_100BASET(s) (((s) & MII_AR8031_PSSR_100MBPS) == ((s) & MII_AR8031_PSSR_SPEEDMASK)) +# define BOARD_PHY_1000BASET(s) (((s) & MII_AR8031_PSSR_1000MBPS) == ((s) & MII_AR8031_PSSR_SPEEDMASK)) +# define BOARD_PHY_ISDUPLEX(s) (((s) & MII_AR8031_PSSR_DUPLEX) != 0) #else # error "Unrecognized or missing PHY selection" #endif @@ -216,7 +226,7 @@ * = 23 */ -#define IMX_MII_SPEED 0x38 /* 100Mbs. Revisit and remove hardcoded value */ +#define IMX_MII_SPEED 0xd /* 1000Mbs. Revisit and remove hardcoded value */ #if IMX_MII_SPEED > 63 # error "IMX_MII_SPEED is out-of-range" #endif @@ -377,7 +387,7 @@ static int imx_phyintenable(struct imx_driver_s *priv); #endif static inline void imx_initmii(struct imx_driver_s *priv); -#if 0 /* TODO */ +#ifndef CONFIG_IMX_ENET_WITH_QEMU static int imx_writemii(struct imx_driver_s *priv, uint8_t phyaddr, uint8_t regaddr, uint16_t data); static int imx_readmii(struct imx_driver_s *priv, uint8_t phyaddr, @@ -1327,13 +1337,18 @@ static int imx_ifup_action(struct net_driver_s *dev, bool resetphy) /* And enable the MAC itself */ regval = imx_enet_getreg32(priv, IMX_ENET_ECR_OFFSET); - regval |= ENET_ECR_ETHEREN + regval |= ENET_ECR_ETHEREN | ENET_ECR_SPEED #ifdef IMX_USE_DBSWAP | ENET_ECR_DBSWP #endif ; + imx_enet_putreg32(priv, regval, IMX_ENET_ECR_OFFSET); + /* Set TX FIFO write to avoid TX FIFO underrun */ + + imx_enet_putreg32(priv, 0x3f, IMX_ENET_TFWR_OFFSET); + /* Indicate that there have been empty receive buffers produced */ imx_enet_putreg32(priv, ENET_RDAR, IMX_ENET_RDAR_OFFSET); @@ -1873,7 +1888,7 @@ static void imx_initmii(struct imx_driver_s *priv) * ****************************************************************************/ -#if 0 /* TODO */ +#ifndef CONFIG_IMX_ENET_WITH_QEMU static int imx_writemii(struct imx_driver_s *priv, uint8_t phyaddr, uint8_t regaddr, uint16_t data) { @@ -1935,7 +1950,7 @@ static int imx_writemii(struct imx_driver_s *priv, uint8_t phyaddr, * ****************************************************************************/ -#if 0 /* TODO */ +#ifndef CONFIG_IMX_ENET_WITH_QEMU static int imx_readmii(struct imx_driver_s *priv, uint8_t phyaddr, uint8_t regaddr, uint16_t *data) { @@ -2005,7 +2020,7 @@ static int imx_readmii(struct imx_driver_s *priv, uint8_t phyaddr, static inline int imx_initphy(struct imx_driver_s *priv, bool renogphy) { -#if 0 /* TODO */ +#ifndef CONFIG_IMX_ENET_WITH_QEMU uint32_t rcr; uint32_t tcr; uint32_t racc; @@ -2160,6 +2175,23 @@ static inline int imx_initphy(struct imx_driver_s *priv, bool renogphy) MII_ADVERTISE_10BASETXHALF | MII_ADVERTISE_CSMA); +#elif defined (CONFIG_ETH0_PHY_AR8031) + + /* Advertise Gigabit support */ + + imx_writemii(priv, phyaddr, MII_ADVERTISE, + MII_ADVERTISE_1000XFULL | + MII_ADVERTISE_1000XHALF | + MII_ADVERTISE_100BASETXFULL | + MII_ADVERTISE_100BASETXHALF | + MII_ADVERTISE_10BASETXFULL | + MII_ADVERTISE_10BASETXHALF | + MII_ADVERTISE_CSMA); + + /* Then reset PHY */ + + ninfo("AR8031: *** reset phy (phyaddr=0x%x) \n", phyaddr); + imx_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); #endif /* Start auto negotiation */ @@ -2253,16 +2285,13 @@ static inline int imx_initphy(struct imx_driver_s *priv, bool renogphy) * configuration and the auto negotiation results. */ -#ifdef CONFIG_IMX_ENETUSEMII rcr = ENET_RCR_CRCFWD | (CONFIG_NET_ETH_PKTSIZE + CONFIG_NET_GUARDSIZE) << ENET_RCR_MAX_FL_SHIFT | +#ifdef CONFIG_IMX_ENETUSEMII ENET_RCR_MII_MODE; #else - rcr = ENET_RCR_RMII_MODE | ENET_RCR_CRCFWD | - (CONFIG_NET_ETH_PKTSIZE + CONFIG_NET_GUARDSIZE) - << ENET_RCR_MAX_FL_SHIFT | - ENET_RCR_MII_MODE; + ENET_RCR_RGMII_EN; #endif tcr = 0; @@ -2307,6 +2336,14 @@ static inline int imx_initphy(struct imx_driver_s *priv, bool renogphy) ninfo("%s: 100 Base-T\n", BOARD_PHY_NAME); } +#ifdef CONFIG_ETH0_PHY_AR8031 + else if (BOARD_PHY_1000BASET(phydata)) + { + /* 1000 Mbps */ + + ninfo("%s: 1000 Base-T\n", BOARD_PHY_NAME); + } +#endif else { /* This might happen if Autonegotiation did not complete(?) */ @@ -2488,7 +2525,7 @@ int imx_netinitialize(int intf) #endif priv->dev.d_private = g_enet; /* Used to recover private state from dev */ -#if 0 /* TODO */ +#if 0 /* NOTE: clock & iomux are set in u-boot */ uint32_t regval; /* Configure ENET1_TX_CLK */ @@ -2519,7 +2556,7 @@ int imx_netinitialize(int intf) imx_config_gpio(GPIO_ENET_RX_ER); #endif -#endif /* TODO */ +#endif /* if 0 */ /* Attach the Ethernet MAC IEEE 1588 timer interrupt handler */ @@ -2556,16 +2593,16 @@ int imx_netinitialize(int intf) /* hardcoded offset: todo: need proper header file */ -#if 0 /* TODO */ - uidl = getreg32(IMX_OCOTP_BASE + 0x410); - uidml = getreg32(IMX_OCOTP_BASE + 0x420); +#ifndef CONFIG_IMX_ENET_WITH_QEMU + uidl = getreg32(IMX_OCOTPCTRL_VBASE + 0x620); + uidml = getreg32(IMX_OCOTPCTRL_VBASE + 0x630); +#else + uidml |= 0x00000200; + uidml &= 0x0000feff; #endif mac = priv->dev.d_mac.ether.ether_addr_octet; - uidml |= 0x00000200; - uidml &= 0x0000feff; - mac[0] = (uidml & 0x0000ff00) >> 8; mac[1] = (uidml & 0x000000ff); mac[2] = (uidl & 0xff000000) >> 24;