You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/04/25 03:45:28 UTC

[nuttx] 03/04: arch: imx6: Add support for AR8031 gigabit ethernet phy

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit fb6bef2c2d768dfee37efd4bff75cff49f38d727
Author: Masayuki Ishikawa <ma...@gmail.com>
AuthorDate: Mon Apr 17 10:47:39 2023 +0900

    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 <Ma...@jp.sony.com>
---
 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;