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;