From 4686e08c8931ffe4f02137ec203000fbf339515d Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 27 Sep 2013 13:12:04 -0600 Subject: SAMA5 GMAC and GMII support is code complete and ready for test --- nuttx/TODO | 7 +- nuttx/arch/arm/src/sama5/Kconfig | 119 ++----- nuttx/arch/arm/src/sama5/chip/sam_emac.h | 1 + nuttx/arch/arm/src/sama5/chip/sam_gmac.h | 1 + nuttx/arch/arm/src/sama5/sam_emac.c | 16 +- nuttx/arch/arm/src/sama5/sam_gmac.c | 542 ++++++++++++++++--------------- nuttx/include/nuttx/net/gmii.h | 65 +++- nuttx/include/nuttx/net/mii.h | 12 +- 8 files changed, 376 insertions(+), 387 deletions(-) diff --git a/nuttx/TODO b/nuttx/TODO index 6b6dee76f..4736b88b3 100644 --- a/nuttx/TODO +++ b/nuttx/TODO @@ -1,4 +1,4 @@ -NuttX TODO List (Last updated August 2, 2013) +NuttX TODO List (Last updated September 27, 2013) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with @@ -749,6 +749,11 @@ o Network (net/, drivers/net) connection (lipaddr) and verifying that it is in the subnet served by the driver. + Another issue: When sending packets to another subnet, the + current logic falls back and uses ETH0 if it cannot find the + device for the subnet. That lookup would need to be smarter... + perhaps it needs a routing table. + Status: Open. Nothing will probably be done until I have a platform with two network interfaces that I need to support. Priority: Medium, The feature is not important, but it is important diff --git a/nuttx/arch/arm/src/sama5/Kconfig b/nuttx/arch/arm/src/sama5/Kconfig index 21638744f..855945f42 100644 --- a/nuttx/arch/arm/src/sama5/Kconfig +++ b/nuttx/arch/arm/src/sama5/Kconfig @@ -314,121 +314,48 @@ config SAMA5_GMAC_PHYINIT provide sam_phyinitialize(); The SAMA5 GMAC driver will call this function one time before it first uses the PHY. -config SAMA5_GMAC_GMII - bool "Use MII interface" - default n - ---help--- - Support Ethernet MII interface (vs RMII). - -config SAMA5_GMAC_RGMII - bool - default y if !SAMA5_GMAC_GMII - default n if SAMA5_GMAC_GMII - config SAMA5_GMAC_AUTONEG bool "Use autonegotiation" default y ---help--- Use PHY autonegotiation to determine speed and mode +if !SAMA5_GMAC_AUTONEG + config SAMA5_GMAC_ETHFD bool "Full duplex" default n - depends on !SAMA5_GMAC_AUTONEG - ---help--- - If SAMA5_GMAC_AUTONEG is not defined, then this may be defined to select full duplex - mode. Default: half-duplex - -config SAMA5_GMAC_ETH100MBPS - bool "100 Mbps" - default n - depends on !SAMA5_GMAC_AUTONEG - ---help--- - If SAMA5_GMAC_AUTONEG is not defined, then this may be defined to select 100 MBps - speed. Default: 10 Mbps - -config SAMA5_GMAC_PHYSR - int "PHY Status Register Address (decimal)" - depends on SAMA5_GMAC_AUTONEG - ---help--- - This must be provided if SAMA5_GMAC_AUTONEG is defined. The PHY status register - address may diff from PHY to PHY. This configuration sets the address of - the PHY status register. - -config SAMA5_GMAC_PHYSR_ALTCONFIG - bool "PHY Status Alternate Bit Layout" - default n - depends on SAMA5_GMAC_AUTONEG - ---help--- - Different PHYs present speed and mode information in different ways. Some - will present separate information for speed and mode (this is the default). - Those PHYs, for example, may provide a 10/100 Mbps indication and a separate - full/half duplex indication. This options selects an alternative representation - where speed and mode information are combined. This might mean, for example, - separate bits for 10HD, 100HD, 10FD and 100FD. - -config SAMA5_GMAC_PHYSR_SPEED - hex "PHY Speed Mask" - depends on SAMA5_GMAC_AUTONEG && !SAMA5_GMAC_PHYSR_ALTCONFIG - ---help--- - This must be provided if SAMA5_GMAC_AUTONEG is defined. This provides bit mask - for isolating the 10 or 100MBps speed indication. - -config SAMA5_GMAC_PHYSR_100MBPS - hex "PHY 100Mbps Speed Value" - depends on SAMA5_GMAC_AUTONEG && !SAMA5_GMAC_PHYSR_ALTCONFIG - ---help--- - This must be provided if SAMA5_GMAC_AUTONEG is defined. This provides the value - of the speed bit(s) indicating 100MBps speed. - -config SAMA5_GMAC_PHYSR_MODE - hex "PHY Mode Mask" - depends on SAMA5_GMAC_AUTONEG && !SAMA5_GMAC_PHYSR_ALTCONFIG - ---help--- - This must be provided if SAMA5_GMAC_AUTONEG is defined. This provide bit mask - for isolating the full or half duplex mode bits. - -config SAMA5_GMAC_PHYSR_FULLDUPLEX - hex "PHY Full Duplex Mode Value" - depends on SAMA5_GMAC_AUTONEG && !SAMA5_GMAC_PHYSR_ALTCONFIG ---help--- - This must be provided if SAMA5_GMAC_AUTONEG is defined. This provides the - value of the mode bits indicating full duplex mode. + If SAMA5_GMAC_AUTONEG is not defined, then this may be defined to + select full duplex mode. Default: half-duplex -config SAMA5_GMAC_PHYSR_ALTMODE - hex "PHY Mode Mask" - depends on SAMA5_GMAC_AUTONEG && SAMA5_GMAC_PHYSR_ALTCONFIG +choice + prompt "GMAC Speed" + default SAMA5_GMAC_ETH100MBPS ---help--- - This must be provided if SAMA5_GMAC_AUTONEG is defined. This provide bit mask - for isolating the speed and full/half duplex mode bits. + If autonegation is not used, then you must select the fixed speed + of the PHY -config SAMA5_GMAC_PHYSR_10HD - hex "10MBase-T Half Duplex Value" - depends on SAMA5_GMAC_AUTONEG && SAMA5_GMAC_PHYSR_ALTCONFIG +config SAMA5_GMAC_ETH10MBPS + bool "10 Mbps" ---help--- - This must be provided if SAMA5_GMAC_AUTONEG is defined. This is the value - under the bit mask that represents the 10Mbps, half duplex setting. + If SAMA5_GMAC_AUTONEG is not defined, then this may be defined to select 10 MBps + speed. Default: 100 Mbps -config SAMA5_GMAC_PHYSR_100HD - hex "100Base-T Half Duplex Value" - depends on SAMA5_GMAC_AUTONEG && SAMA5_GMAC_PHYSR_ALTCONFIG +config SAMA5_GMAC_ETH100MBPS + bool "100 Mbps" ---help--- - This must be provided if SAMA5_GMAC_AUTONEG is defined. This is the value - under the bit mask that represents the 100Mbps, half duplex setting. + If SAMA5_GMAC_AUTONEG is not defined, then this may be defined to select 100 MBps + speed. Default: 100 Mbps -config SAMA5_GMAC_PHYSR_10FD - hex "10Base-T Full Duplex Value" - depends on SAMA5_GMAC_AUTONEG && SAMA5_GMAC_PHYSR_ALTCONFIG +config SAMA5_GMAC_ETH1000MBPS + bool "1000 Mbps" ---help--- - This must be provided if SAMA5_GMAC_AUTONEG is defined. This is the value - under the bit mask that represents the 10Mbps, full duplex setting. + If SAMA5_GMAC_AUTONEG is not defined, then this may be defined to select 1000 MBps + speed. Default: 100 Mbps -config SAMA5_GMAC_PHYSR_100FD - hex "100Base-T Full Duplex Value" - depends on SAMA5_GMAC_AUTONEG && SAMA5_GMAC_PHYSR_ALTCONFIG - ---help--- - This must be provided if SAMA5_GMAC_AUTONEG is defined. This is the value - under the bit mask that represents the 100Mbps, full duplex setting. +endchoice # GMAC speed +endif # !SAMA5_GMAC_AUTONEG config SAMA5_GMAC_REGDEBUG bool "Register-Level Debug" diff --git a/nuttx/arch/arm/src/sama5/chip/sam_emac.h b/nuttx/arch/arm/src/sama5/chip/sam_emac.h index 86f7c766f..f86a8dc97 100644 --- a/nuttx/arch/arm/src/sama5/chip/sam_emac.h +++ b/nuttx/arch/arm/src/sama5/chip/sam_emac.h @@ -237,6 +237,7 @@ #define EMAC_INT_WOL (1 << 14) /* Bit 14: Wake On LAN */ #define EMAC_INT_ALL (0x00007cff) +#define EMAC_INT_UNUSED (0xffff8300) /* Phy Maintenance Register */ diff --git a/nuttx/arch/arm/src/sama5/chip/sam_gmac.h b/nuttx/arch/arm/src/sama5/chip/sam_gmac.h index ffb42aa66..5b9be39fc 100644 --- a/nuttx/arch/arm/src/sama5/chip/sam_gmac.h +++ b/nuttx/arch/arm/src/sama5/chip/sam_gmac.h @@ -583,6 +583,7 @@ #define GMAC_INT_WOL (1 << 28) /* Bit 28: Wake On LAN (not in IMR) */ #define GMAC_INT_ALL (0x17fcfcff) +#define GMAC_INT_UNUSED (0xe8030300) /* PHY Maintenance Register */ diff --git a/nuttx/arch/arm/src/sama5/sam_emac.c b/nuttx/arch/arm/src/sama5/sam_emac.c index 1c5198020..ea81bfd01 100644 --- a/nuttx/arch/arm/src/sama5/sam_emac.c +++ b/nuttx/arch/arm/src/sama5/sam_emac.c @@ -1307,7 +1307,7 @@ static int sam_emac_interrupt(int irq, void *context) tsr = sam_getreg(priv, SAM_EMAC_TSR); imr = sam_getreg(priv, SAM_EMAC_IMR); - pending = isr & ~(imr | 0xffc300); + pending = isr & ~(imr | EMAC_INT_UNUSED); nllvdbg("isr: %08x pending: %08x\n", isr, pending); /* Check for the completion of a transmission. This should be done before @@ -2159,10 +2159,12 @@ static int sam_autonegotiate(struct sam_emac_s *priv) nllvdbg("PHYID2: %04x PHY address: %02x\n", phyid2, priv->phyaddr); if (phyid1 == MII_OUI_MSB && - ((phyid2 & MII_PHYID2_OUI) >> 10) == MII_OUI_LSB) + ((phyid2 & MII_PHYID2_OUI_MASK) >> MII_PHYID2_OUI_SHIFT) == MII_OUI_LSB) { - nllvdbg(" Vendor Model Number: %04x\n", ((phyid2 >> 4) & 0x3f)); - nllvdbg(" Model Revision Number: %04x\n", (phyid2 & 7)); + nllvdbg(" Vendor Model Number: %04x\n", + (phyid2 & MII_PHYID2_MODEL_MASK) >> MII_PHYID2_MODEL_SHIFT); + nllvdbg(" Model Revision Number: %04x\n", + (phyid2 & MII_PHYID2_REV_MASK) >> MII_PHYID2_REV_SHIFT); } else { @@ -2570,6 +2572,12 @@ static void sam_txreset(struct sam_emac_s *priv) txdesc[CONFIG_SAMA5_EMAC_NTXBUFFERS - 1].status = EMACTXD_STA_USED | EMACTXD_STA_WRAP; + /* Flush the entire TX descriptor table to RAM */ + + cp15_clean_dcache((uintptr_t)txdesc, + (uintptr_t)txdesc + + CONFIG_SAMA5_EMAC_NTXBUFFERS * sizeof(struct emac_txdesc_s)); + /* Set the Transmit Buffer Queue Pointer Register */ physaddr = sam_physramaddr((uintptr_t)txdesc); diff --git a/nuttx/arch/arm/src/sama5/sam_gmac.c b/nuttx/arch/arm/src/sama5/sam_gmac.c index 6971d7a85..bed51d2ac 100644 --- a/nuttx/arch/arm/src/sama5/sam_gmac.c +++ b/nuttx/arch/arm/src/sama5/sam_gmac.c @@ -103,84 +103,15 @@ # error "CONFIG_SAMA5_GMAC_PHYADDR must be defined in the NuttX configuration" #endif -#if !defined(CONFIG_SAMA5_GMAC_GMII) && !defined(CONFIG_SAMA5_GMAC_RGMII) -# warning "Neither CONFIG_SAMA5_GMAC_GMII nor CONFIG_SAMA5_GMAC_RGMII defined" -#endif - -#if defined(CONFIG_SAMA5_GMAC_GMII) && defined(CONFIG_SAMA5_GMAC_RGMII) -# error "Both CONFIG_SAMA5_GMAC_GMII and CONFIG_SAMA5_GMAC_RGMII defined" -#endif - -#ifdef CONFIG_SAMA5_GMAC_AUTONEG -# ifndef CONFIG_SAMA5_GMAC_PHYSR -# error "CONFIG_SAMA5_GMAC_PHYSR must be defined in the NuttX configuration" -# endif -# ifdef CONFIG_SAMA5_GMAC_PHYSR_ALTCONFIG -# ifndef CONFIG_SAMA5_GMAC_PHYSR_ALTMODE -# error "CONFIG_SAMA5_GMAC_PHYSR_ALTMODE must be defined in the NuttX configuration" -# endif -# ifndef CONFIG_SAMA5_GMAC_PHYSR_10HD -# error "CONFIG_SAMA5_GMAC_PHYSR_10HD must be defined in the NuttX configuration" -# endif -# ifndef CONFIG_SAMA5_GMAC_PHYSR_100HD -# error "CONFIG_SAMA5_GMAC_PHYSR_100HD must be defined in the NuttX configuration" -# endif -# ifndef CONFIG_SAMA5_GMAC_PHYSR_10FD -# error "CONFIG_SAMA5_GMAC_PHYSR_10FD must be defined in the NuttX configuration" -# endif -# ifndef CONFIG_SAMA5_GMAC_PHYSR_100FD -# error "CONFIG_SAMA5_GMAC_PHYSR_100FD must be defined in the NuttX configuration" -# endif -# else -# ifndef CONFIG_SAMA5_GMAC_PHYSR_SPEED -# error "CONFIG_SAMA5_GMAC_PHYSR_SPEED must be defined in the NuttX configuration" -# endif -# ifndef CONFIG_SAMA5_GMAC_PHYSR_100MBPS -# error "CONFIG_SAMA5_GMAC_PHYSR_100MBPS must be defined in the NuttX configuration" -# endif -# ifndef CONFIG_SAMA5_GMAC_PHYSR_MODE -# error "CONFIG_SAMA5_GMAC_PHYSR_MODE must be defined in the NuttX configuration" -# endif -# ifndef CONFIG_SAMA5_GMAC_PHYSR_FULLDUPLEX -# error "CONFIG_SAMA5_GMAC_PHYSR_FULLDUPLEX must be defined in the NuttX configuration" -# endif -# endif -#endif - /* PHY definitions */ #ifdef SAMA5_GMAC_PHY_KSZ90x1 # define GMII_OUI_MSB 0x0022 -# define GMII_OUI_LSB 0x05 +# define GMII_OUI_LSB GMII_PHYID2_OUI(5) #else # error Unknown PHY #endif -#ifdef CONFIG_SAMA5_GMAC_PHYSR_ALTCONFIG - -# define PHYSR_MODE(sr) ((sr) & CONFIG_SAMA5_GMAC_PHYSR_ALTMODE) -# define PHYSR_ISMODE(sr,m) (PHYSR_MODE(sr) == (m)) - -# define PHYSR_IS10HDX(sr) PHYSR_ISMODE(sr,CONFIG_SAMA5_GMAC_PHYSR_10HD) -# define PHYSR_IS100HDX(sr) PHYSR_ISMODE(sr,CONFIG_SAMA5_GMAC_PHYSR_100HD) -# define PHYSR_IS10FDX(sr) PHYSR_ISMODE(sr,CONFIG_SAMA5_GMAC_PHYSR_10FD) -# define PHYSR_IS100FDX(sr) PHYSR_ISMODE(sr,CONFIG_SAMA5_GMAC_PHYSR_100FD) - -#else - -# define PHYSR_MODESPEED (CONFIG_PHYSR_MODE | CONFIG_PHYSR_SPEED) -# define PHYSR_10HDX (0) -# define PHYSR_100HDX (CONFIG_PHYSR_100MBPS) -# define PHYSR_10FDX (CONFIG_PHYSR_FULLDUPLEX) -# define PHYSR_100FDX (CONFIG_PHYSR_FULLDUPLEX | CONFIG_PHYSR_100MBPS) - -# define PHYSR_IS10HDX(sr) (((sr) & PHYSR_MODESPEED) == PHYSR_10HDX) -# define PHYSR_IS100HDX(sr) (((sr) & PHYSR_MODESPEED) == PHYSR_100HDX) -# define PHYSR_IS10FDX(sr) (((sr) & PHYSR_MODESPEED) == PHYSR_10FDX) -# define PHYSR_IS100FDX(sr) (((sr) & PHYSR_MODESPEED) == PHYSR_100FDX) - -#endif - /* GMAC buffer sizes, number of buffers, and number of descriptors. * * REVISIT: The CONFIG_NET_MULTIBUFFER might be useful. It might be possible @@ -384,8 +315,11 @@ static int sam_phyread(struct sam_gmac_s *priv, uint8_t phyaddr, uint8_t regaddr, uint16_t *phyval); static int sam_phywrite(struct sam_gmac_s *priv, uint8_t phyaddr, uint8_t regaddr, uint16_t phyval); +#ifdef CONFIG_SAMA5_GMAC_AUTONEG static int sam_autonegotiate(struct sam_gmac_s *priv); -static bool sam_linkup(struct sam_gmac_s *priv); +#else +static void sam_linkspeed(struct sam_gmac_s *priv); +#endif static void sam_mdcclock(struct sam_gmac_s *priv); static int sam_phyinit(struct sam_gmac_s *priv); @@ -677,7 +611,7 @@ static void sam_buffer_free(struct sam_gmac_s *priv) * Function: sam_transmit * * Description: - * Start hardware transmission. Called either from the txdone interrupt + * Start hardware transmission. Called either from the TX done interrupt * handling or from watchdog based polling. * * Parameters: @@ -907,7 +841,7 @@ static void sam_dopoll(struct sam_gmac_s *priv) static int sam_recvframe(struct sam_gmac_s *priv) { - struct gmac_rxdesc_s *rxdesc; + volatile struct gmac_rxdesc_s *rxdesc; struct uip_driver_s *dev; const uint8_t *src; uint8_t *dest; @@ -1308,7 +1242,7 @@ static int sam_gmac_interrupt(int irq, void *context) tsr = sam_getreg(priv, SAM_GMAC_TSR); imr = sam_getreg(priv, SAM_GMAC_IMR); - pending = isr & ~(imr | 0xffc300); + pending = isr & ~(imr | GMAC_INT_UNUSED); nllvdbg("isr: %08x pending: %08x\n", isr, pending); /* Check for the completion of a transmission. This should be done before @@ -1373,6 +1307,22 @@ static int sam_gmac_interrupt(int irq, void *context) clrbits |= GMAC_TSR_UND; } + /* Check for HRESP not OK */ + + if ((tsr & GMAC_TSR_HRESP) != 0) + { + nlldbg("ERROR: HRESP not OK: %08x\n", tsr); + clrbits |= GMAC_TSR_HRESP; + } + + /* Check for Late Collitions (LCO) */ + + if ((tsr & GMAC_TSR_LCO) != 0) + { + nlldbg("ERROR: Late collision: %08x\n", tsr); + clrbits |= GMAC_TSR_LCO; + } + /* Clear status */ sam_putreg(priv, SAM_GMAC_TSR, clrbits); @@ -1427,6 +1377,14 @@ static int sam_gmac_interrupt(int irq, void *context) clrbits |= GMAC_RSR_BNA; } + /* Check for HRESP not OK (HNO)*/ + + if ((rsr & GMAC_RSR_HNO) != 0) + { + nlldbg("ERROR: HRESP not OK: %08x\n", rsr); + clrbits |= GMAC_RSR_HNO; + } + /* Clear status */ sam_putreg(priv, SAM_GMAC_RSR, clrbits); @@ -1574,6 +1532,7 @@ static int sam_ifup(struct uip_driver_s *dev) /* Initialize for PHY access */ + sam_phyreset(priv); ret = sam_phyinit(priv); if (ret < 0) { @@ -1581,6 +1540,7 @@ static int sam_ifup(struct uip_driver_s *dev) return ret; } +#ifdef CONFIG_SAMA5_GMAC_AUTONEG /* Auto Negotiate, working in RMII mode */ ret = sam_autonegotiate(priv); @@ -1589,9 +1549,11 @@ static int sam_ifup(struct uip_driver_s *dev) nlldbg("ERROR: sam_autonegotiate failed: %d\n", ret); return ret; } +#else + /* Just force the configured link speed */ - while (sam_linkup(priv) == 0); - nllvdbg("Link detected \n"); + sam_linkspeed(priv); +#endif /* Enable normal MAC operation */ @@ -1791,22 +1753,21 @@ static void sam_phydump(struct sam_gmac_s *priv) sam_enablemdio(priv); -#ifdef CONFIG_SAMA5_GMAC_RGMII - nllvdbg("RMII Registers (Address %02x)\n", priv->phyaddr); -#else /* defined(CONFIG_SAMA5_GMAC_GMII) */ - nllvdbg("MII Registers (Address %02x)\n", priv->phyaddr); -#endif - + nllvdbg("GMII Registers (Address %02x)\n", priv->phyaddr); sam_phyread(priv, priv->phyaddr, GMII_MCR, &phyval); - nllvdbg(" MCR: %04x\n", phyval); + nllvdbg(" MCR: %04x\n", phyval); sam_phyread(priv, priv->phyaddr, GMII_MSR, &phyval); - nllvdbg(" MSR: %04x\n", phyval); + nllvdbg(" MSR: %04x\n", phyval); sam_phyread(priv, priv->phyaddr, GMII_ADVERTISE, &phyval); - nllvdbg(" ADVERTISE: %04x\n", phyval); + nllvdbg(" ADVERTISE: %04x\n", phyval); sam_phyread(priv, priv->phyaddr, GMII_LPA, &phyval); - nllvdbg(" LPR: %04x\n", phyval); - sam_phyread(priv, priv->phyaddr, CONFIG_SAMA5_GMAC_PHYSR, &phyval); - nllvdbg(" PHYSR: %04x\n", phyval); + nllvdbg(" LPR: %04x\n", phyval); + sam_phyread(priv, priv->phyaddr, GMII_1000BTCR, &phyval); + nllvdbg(" 1000BTCR: %04x\n", phyval); + sam_phyread(priv, priv->phyaddr, GMII_1000BTSR, &phyval); + nllvdbg(" 1000BTSR: %04x\n", phyval); + sam_phyread(priv, priv->phyaddr, GMII_ESTATUS, &phyval); + nllvdbg(" ESTATUS: %04x\n", phyval); /* Disable management port */ @@ -1831,7 +1792,7 @@ static void sam_phydump(struct sam_gmac_s *priv) static void sam_enablemdio(struct sam_gmac_s *priv) { uint32_t regval; - uint32_t ncr; + uint32_t enables; /* Enable management port */ @@ -2042,8 +2003,6 @@ static int sam_phyfind(struct sam_gmac_s *priv, uint8_t *phyaddr) { nllvdbg(" PHYID1: %04x PHY addr: %d\n", phyval, candidate); *phyaddr = candidate; - sam_phyread(priv, candidate, CONFIG_SAMA5_GMAC_PHYSR, &phyval); - nllvdbg(" PHYSR: %04x PHY addr: %d\n", phyval, candidate); } /* Disable management port */ @@ -2173,15 +2132,19 @@ static int sam_phywrite(struct sam_gmac_s *priv, uint8_t phyaddr, * ****************************************************************************/ +#ifdef CONFIG_SAMA5_GMAC_AUTONEG static int sam_autonegotiate(struct sam_gmac_s *priv) { uint32_t regval; + uint32_t ncr; + uint32_t linkmode; + uint16_t phyval; uint16_t phyid1; uint16_t phyid2; - uint16_t mcr; - uint16_t msr; uint16_t advertise; uint16_t lpa; + uint16_t btcr; + uint16_t btsr; int timeout; int ret; @@ -2189,58 +2152,57 @@ static int sam_autonegotiate(struct sam_gmac_s *priv) sam_enablemdio(priv); - /* Verify tht we can read the PHYID register */ + /* Read the MS bits of the OUI from Pthe PHYID1 register */ ret = sam_phyread(priv, priv->phyaddr, GMII_PHYID1, &phyid1); if (ret < 0) { - nlldbg("ERROR: Failed to read PHYID1\n"); + nlldbg("ERROR: Failed to read PHYID1 register\n"); goto errout; } nllvdbg("PHYID1: %04x PHY address: %02x\n", phyid1, priv->phyaddr); + /* Read the LS bits of the OUI from Pthe PHYID2 register */ + ret = sam_phyread(priv, priv->phyaddr, GMII_PHYID2, &phyid2); if (ret < 0) { - nlldbg("ERROR: Failed to read PHYID2\n"); + nlldbg("ERROR: Failed to read PHYID2 register\n"); goto errout; } nllvdbg("PHYID2: %04x PHY address: %02x\n", phyid2, priv->phyaddr); if (phyid1 == GMII_OUI_MSB && - ((phyid2 & GMII_PHYID2_OUI) >> 10) == GMII_OUI_LSB) + (phyid2 & GMII_PHYID2_OUI_MASK) == GMII_OUI_LSB) { - nllvdbg(" Vendor Model Number: %04x\n", ((phyid2 >> 4) & 0x3f)); - nllvdbg(" Model Revision Number: %04x\n", (phyid2 & 7)); + nllvdbg(" Vendor Model Number: %04x\n", + (phyid2 & GMII_PHYID2_MODEL_MASK) >> GMII_PHYID2_MODEL_SHIFT); + nllvdbg(" Model Revision Number: %04x\n", + (phyid2 & GMII_PHYID2_REV_MASK) >> GMII_PHYID2_REV_SHIFT); } else { - nlldbg("ERROR: PHY not recognized\n"); + nlldbg("ERROR: PHY not recognized: PHYID1=%04x PHYID2=%04x\n", + phyid1, phyid2); } - /* Setup control register */ +#ifdef SAMA5_GMAC_PHY_KSZ90x1 + /* Set up the KSZ9020/31 PHY */ - ret = sam_phyread(priv, priv->phyaddr, GMII_MCR, &mcr); - if (ret < 0) - { - nlldbg("ERROR: Failed to read MCR\n"); - goto errout; - } + phyval = GMII_KSZ90x1_RCCPSR | GMII_ERCR_WRITE; + sam_phywrite(priv, priv->phyaddr, GMII_ERCR, phyval); + sam_phywrite(priv, priv->phyaddr, GMII_ERDWR, 0xf2f4); - mcr &= ~GMII_MCR_ANENABLE; /* Remove autonegotiation enable */ - mcr &= ~(GMII_MCR_LOOPBACK | GMII_MCR_PDOWN); - mcr |= GMII_MCR_ISOLATE; /* Electrically isolate PHY */ + phyval = GMII_KSZ90x1_RRDPSR | GMII_ERCR_WRITE; + sam_phywrite(priv, priv->phyaddr, GMII_ERCR, phyval); + sam_phywrite(priv, priv->phyaddr, GMII_ERDWR, 0x2222); - ret = sam_phywrite(priv, priv->phyaddr, GMII_MCR, mcr); - if (ret < 0) - { - nlldbg("ERROR: Failed to write MCR\n"); - goto errout; - } + ret = sam_phywrite(priv, priv->phyaddr, GMII_KSZ90x1_ICS, 0xff00); +#endif - /* Set the Auto_negotiation Advertisement Register MII advertising for + /* Set the Auto_negotiation Advertisement Register, MII advertising for * Next page 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 */ @@ -2251,56 +2213,65 @@ static int sam_autonegotiate(struct sam_gmac_s *priv) ret = sam_phywrite(priv, priv->phyaddr, GMII_ADVERTISE, advertise); if (ret < 0) { - nlldbg("ERROR: Failed to write ANAR\n"); + nlldbg("ERROR: Failed to write ADVERTISE register\n"); goto errout; } - /* Read and modify control register */ + /* Modify the 1000Base-T control register to advertise 1000Base-T full + * and half duplex support. + */ - ret = sam_phyread(priv, priv->phyaddr, GMII_MCR, &mcr); + ret = sam_phyread(priv, priv->phyaddr, GMII_1000BTCR, &btcr); if (ret < 0) { - nlldbg("ERROR: Failed to read MCR\n"); + nlldbg("ERROR: Failed to read 1000BTCR register: %d\n", ret); goto errout; } - mcr |= (GMII_MCR_SPEED100 | GMII_MCR_ANENABLE | GMII_MCR_FULLDPLX); - ret = sam_phywrite(priv, priv->phyaddr, GMII_MCR, mcr); + btcr |= GMII_1000BTCR_1000BASETFULL | GMII_1000BTCR_1000BASETHALF; + + ret = sam_phywrite(priv, priv->phyaddr, GMII_1000BTCR, btcr); if (ret < 0) { - nlldbg("ERROR: Failed to write MCR\n"); + nlldbg("ERROR: Failed to write 1000BTCR register: %d\n", ret); goto errout; } /* Restart Auto_negotiation */ - mcr |= GMII_MCR_ANRESTART; - mcr &= ~GMII_MCR_ISOLATE; + ret = sam_phyread(priv, priv->phyaddr, GMII_MCR, &phyval); + if (ret < 0) + { + nlldbg("ERROR: Failed to read MCR register: %d\n", ret); + goto errout; + } + + phyval |= GMII_MCR_ANRESTART; - ret = sam_phywrite(priv, priv->phyaddr, GMII_MCR, mcr); + ret = sam_phywrite(priv, priv->phyaddr, GMII_MCR, phyval); if (ret < 0) { - nlldbg("ERROR: Failed to write MCR\n"); + nlldbg("ERROR: Failed to write MCR register: %d\n", ret); goto errout; } - nllvdbg(" MCR: %04x\n", mcr); + nllvdbg(" MCR: 0x%X\n", phyval); - /* Check AutoNegotiate complete */ + /* Wait for autonegotion to complete */ timeout = 0; for (;;) { - ret = sam_phyread(priv, priv->phyaddr, GMII_MSR, &msr); + ret = sam_phyread(priv, priv->phyaddr, GMII_MSR, &phyval); if (ret < 0) { - nlldbg("ERROR: Failed to read MSR\n"); + nlldbg("ERROR: Failed to read MSR register: %d\n", ret); goto errout; } - /* Completed successfully? */ + /* Check for completion of autonegotiation */ - if ((msr & GMII_MSR_ANEGCOMPLETE) != 0) + if ((phyval & GMII_MSR_ANEGCOMPLETE) != 0) { /* Yes.. break out of the loop */ @@ -2319,55 +2290,110 @@ static int sam_autonegotiate(struct sam_gmac_s *priv) } } - /* Get the AutoNeg Link partner base page */ + /* Setup the GMAC local link speed */ - ret = sam_phyread(priv, priv->phyaddr, GMII_LPA, &lpa); - if (ret < 0) + linkmode = 0; /* 10Base-T Half-Duplex */ + timeout = 0; + + for (;;) { - nlldbg("ERROR: Failed to read ANLPAR\n"); - goto errout; - } + ret = sam_phyread(priv, priv->phyaddr, GMII_1000BTSR, &btsr); + if (ret == 0) + { + nlldbg("ERROR: Failed to read 1000BTSR register: %d\n", ret); + goto errout; + } - /* Setup the GMAC link speed */ + /* Setup the GMAC link speed */ - regval = sam_getreg(priv, SAM_GMAC_NCFGR); - regval &= (GMAC_NCFGR_SPD | GMAC_NCFGR_FD); + if ((btsr & GMII_1000BTSR_LP1000BASETFULL) != 0 && + (btcr & GMII_1000BTCR_1000BASETHALF) != 0) + { + /* Set RGMII for 1000BaseTX and Full Duplex */ - if (((advertise & lpa) & GMII_ADVERTISE_100BASETXFULL) != 0) - { - /* Set MII for 100BaseTX and Full Duplex */ + linkmode = (GMAC_NCFGR_FD | GMAC_NCFGR_GBE); + break; + } + else if ((btsr & GMII_1000BTSR_LP1000BASETHALF) != 0 && + (btcr & GMII_1000BTCR_1000BASETFULL) != 0) + { + /* Set RGMII for 1000BaseT and Half Duplex */ - regval |= (GMAC_NCFGR_SPD | GMAC_NCFGR_FD); - } - else if (((advertise & lpa) & GMII_ADVERTISE_10BASETXFULL) != 0) - { - /* Set MII for 10BaseT and Full Duplex */ + linkmode = GMAC_NCFGR_GBE; + break; + } - regval |= GMAC_NCFGR_FD; - } - else if (((advertise & lpa) & GMII_ADVERTISE_100BASETXHALF) != 0) - { - /* Set MII for 100BaseTX and half Duplex */ + /* Get the Autonegotiation Link partner base page */ - regval |= GMAC_NCFGR_SPD; - } -#if 0 - else if (((advertise & lpa) & GMII_ADVERTISE_10BASETXHALF) != 0) - { - /* set MII for 10BaseT and half Duplex */ + ret = sam_phyread(priv, priv->phyaddr, GMII_LPA, &lpa); + if (ret == 0) + { + nlldbg("ERROR: Failed to read LPA register: %d\n", ret); + goto errout; + } + + /* Setup the GMAC link speed */ + + if ((advertise & GMII_ADVERTISE_100BASETXFULL) != 0 && + (lpa & GMII_LPA_100BASETXFULL) != 0) + { + /* Set RGMII for 100BaseTX and Full Duplex */ + + linkmode = (GMAC_NCFGR_SPD | GMAC_NCFGR_FD); + break; + } + else if ((advertise & GMII_ADVERTISE_10BASETXFULL) != 0 && + (lpa & GMII_LPA_10BASETXFULL) != 0) + { + /* Set RGMII for 10BaseT and Full Duplex */ + + linkmode = GMAC_NCFGR_FD; + break; + } + else if ((advertise & GMII_ADVERTISE_100BASETXHALF) != 0 && + (lpa & GMII_LPA_100BASETXHALF) != 0) + { + /* Set RGMII for 100BaseTX and half Duplex */ + + linkmode = GMAC_NCFGR_SPD; + break; + } + else if ((advertise & GMII_ADVERTISE_10BASETXHALF) != 0 && + (lpa & GMII_LPA_10BASETXHALF) != 0) + { + /* Set RGMII for 10BaseT and half Duplex */ + + break; + } + + /* Check for a timeout */ + + if (++timeout >= PHY_RETRY_MAX) + { + nlldbg("ERROR: TimeOut\n"); + sam_phydump(priv); + ret = -ETIMEDOUT; + goto errout; + } } -#endif + /* Disable RX and TX momentarily */ + + ncr = sam_getreg(priv, SAM_GMAC_NCR); + sam_putreg(priv, SAM_GMAC_NCR, ncr & ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN)); + + /* Modify the NCFGR register based on the negotiated speed and duplex */ + + regval = sam_getreg(priv, SAM_GMAC_NCFGR); + regval &= ~(GMAC_NCFGR_SPD | GMAC_NCFGR_FD | GMAC_NCFGR_GBE); + regval |= linkmode; sam_putreg(priv, SAM_GMAC_NCFGR, regval); + sam_putreg(priv, SAM_GMAC_NCR, ncr); - /* Select RMII/MII */ + /* Enable RGMII enable */ - regval = sam_getreg(priv, SAM_GMAC_UR); -#ifdef CONFIG_SAMA5_GMAC_RGMII + regval = sam_getreg(priv, SAM_GMAC_UR); regval |= GMAC_UR_RGMII; -#else /* defined(CONFIG_SAMA5_GMAC_GMII) */ - regval &= ~GMAC_UR_RGMII; -#endif sam_putreg(priv, SAM_GMAC_UR, regval); errout: @@ -2376,100 +2402,53 @@ errout: sam_disablemdio(priv); return ret; } +#endif /**************************************************************************** - * Function: sam_linkup + * Function: sam_linkspeed * * Description: - * Check if the link is up + * If autonegotiation is not configured, then just force the configuration + * mode * * Parameters: * priv - A reference to the private driver state structure * * Returned Value: - * true: The link is up + * None * ****************************************************************************/ -static bool sam_linkup(struct sam_gmac_s *priv) +#ifndef CONFIG_SAMA5_GMAC_AUTONEG +statoc void sam_linkspeed(struct sam_gmac_s *priv) { uint32_t regval; - uint16_t msr; - uint16_t physr; - bool linkup = false; - int ret; - - /* Enable management port */ - - sam_enablemdio(priv); - - /* Read the PHY MSR register */ - - ret = sam_phyread(priv, priv->phyaddr, GMII_MSR, &msr); - if (ret < 0) - { - nlldbg("ERROR: Failed to read MSR: %d\n", ret); - goto errout; - } + uint32_t ncr; - if ((msr & GMII_MSR_LINKSTATUS) == 0) - { - nlldbg("ERROR: MSR LinkStatus: %04x\n", msr); - goto errout; - } + /* Disable RX and TX momentarily */ - /* Re-configure Link speed */ + ncr = sam_getreg(priv, SAM_GMAC_NCR); + sam_putreg(priv, SAM_GMAC_NCR, ncr & ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN)); - ret = sam_phyread(priv, priv->phyaddr, CONFIG_SAMA5_GMAC_PHYSR, &physr); - if (ret < 0) - { - nlldbg("ERROR: Failed to read PHYSR: %d\n", ret); - goto errout; - } + /* Modify the NCFGR register based on the configured speed and duplex */ regval = sam_getreg(priv, SAM_GMAC_NCFGR); - regval &= ~(GMAC_NCFGR_SPD | GMAC_NCFGR_FD); - - if ((msr & GMII_MSR_100BASETXFULL) != 0 && PHYSR_IS100FDX(physr)) - { - /* Set GMAC for 100BaseTX and Full Duplex */ + regval &= ~(GMAC_NCFGR_SPD | GMAC_NCFGR_FD | GMAC_NCFGR_GBE); - regval |= (GMAC_NCFGR_SPD | GMAC_NCFGR_FD); - } - else if ((msr & GMII_MSR_10BASETXFULL) != 0 && PHYSR_IS10FDX(physr)) - { - /* Set MII for 10BaseT and Full Duplex */ - - regval |= GMAC_NCFGR_FD; - } - - else if ((msr & GMII_MSR_100BASETXHALF) != 0 && PHYSR_IS100HDX(physr)) - { - /* Set MII for 100BaseTX and Half Duplex */ - - regval |= GMAC_NCFGR_SPD; - } - -#if 0 - else if ((msr & GMII_MSR_10BASETXHALF) != 0 && PHYSR_IS10HDX(physr)) - { - /* Set MII for 10BaseT and Half Duplex */ - } +#ifdef SAMA5_GMAC_ETHFD + regval |= GMAC_NCFGR_FD; #endif - sam_putreg(priv, SAM_GMAC_NCFGR, regval); - - /* Start the GMAC transfers */ - - nllvdbg("Link is up\n"); - linkup = true; - -errout: - /* Disable management port */ +#if defined(SAMA5_GMAC_ETH100MBPS) + regval |= GMAC_NCFGR_SPD; +#elif defined(SAMA5_GMAC_ETH1000MBPS) */ + regval |= GMAC_NCFGR_GBE; +#endif - sam_disablemdio(priv); - return linkup; + sam_puttreg(priv, SAM_GMAC_NCFGR, regval); + sam_putreg(priv, SAM_GMAC_NCR, ncr); } +#endif /**************************************************************************** * Function: sam_mdcclock @@ -2631,7 +2610,7 @@ static void sam_txreset(struct sam_gmac_s *priv) /* Disable TX */ - regval = sam_getreg(priv, SAM_GMAC_NCR); + regval = sam_getreg(priv, SAM_GMAC_NCR); regval &= ~GMAC_NCR_TXEN; sam_putreg(priv, SAM_GMAC_NCR, regval); @@ -2641,20 +2620,27 @@ static void sam_txreset(struct sam_gmac_s *priv) priv->txtail = 0; for (ndx = 0; ndx < CONFIG_SAMA5_GMAC_NTXBUFFERS; ndx++) - { - bufaddr = (uint32_t)(&(txbuffer[ndx * GMAC_TX_UNITSIZE])); + { + bufaddr = (uintptr_t)(&(txbuffer[ndx * GMAC_TX_UNITSIZE])); - /* Set the buffer address and mark the descriptor as in used by firmware */ + /* Set the buffer address and mark the descriptor as in used by + * firmware. + */ - physaddr = sam_physramaddr(bufaddr); - txdesc[ndx].addr = physaddr; - txdesc[ndx].status = GMACTXD_STA_USED; - } + physaddr = sam_physramaddr(bufaddr); + txdesc[ndx].addr = physaddr; + txdesc[ndx].status = (uint32_t)GMACTXD_STA_USED; + } /* Mark the final descriptor in the list */ - txdesc[CONFIG_SAMA5_GMAC_NTXBUFFERS - 1].status = - GMACTXD_STA_USED | GMACTXD_STA_WRAP; + txdesc[CONFIG_SAMA5_GMAC_NTXBUFFERS - 1].status = GMACTXD_STA_USED | GMACTXD_STA_WRAP; + + /* Flush the entire TX descriptor table to RAM */ + + cp15_clean_dcache((uintptr_t)txdesc, + (uintptr_t)txdesc + + CONFIG_SAMA5_GMAC_NTXBUFFERS * sizeof(struct gmac_txdesc_s)); /* Set the Transmit Buffer Queue Base Register */ @@ -2682,7 +2668,7 @@ static void sam_rxreset(struct sam_gmac_s *priv) { struct gmac_rxdesc_s *rxdesc = priv->rxdesc; uint8_t *rxbuffer = priv->rxbuffer; - uint32_t bufaddr; + uintptr_t bufaddr; uint32_t physaddr; uint32_t regval; int ndx; @@ -2842,36 +2828,57 @@ static int sam_gmac_configure(struct sam_gmac_s *priv) /* Clear all status bits in the receive status register. */ - regval = (GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA); + regval = (GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA | GMAC_RSR_HNO); sam_putreg(priv, SAM_GMAC_RSR, regval); /* Clear all status bits in the transmit status register */ - regval = (GMAC_TSR_UBR | GMAC_TSR_COL | GMAC_TSR_RLE | GMAC_TSR_TFC | - GMAC_TSR_TXCOMP | GMAC_TSR_UND); + regval = GMAC_TSR_UBR | GMAC_TSR_COL | GMAC_TSR_RLE | GMAC_TSR_TXGO | + GMAC_TSR_TFC | GMAC_TSR_TXCOMP | GMAC_TSR_UND | GMAC_TSR_HRESP | + GMAC_TSR_LCO; sam_putreg(priv, SAM_GMAC_TSR, regval); /* Clear any pending interrupts */ (void)sam_getreg(priv, SAM_GMAC_ISR); - /* Enable/disable the copy of data into the buffers, ignore broadcasts. - * Don't copy FCS. + /* Initial configuration: + * + * SPD = 0 : Assuming 1000Base-T full duplex + * FD = 1 : Assuming 1000Base-T full duplex + * DNVLAN = 0 : Don't discard non-VLAN frames + * JFRAME = 0 : Disable jumbo frames + * CAF : Depends on CONFIG_NET_PROMISCUOUS + * NBC : Depends on CONFIG_SAMA5_GMAC_NBC + * MTIHEN = 0 : Multicast hash disabled + * UNIHEN = 0 : Unicast hash disabled + * MAXFS = 0 : Disable receive 1536 byte frames + * GBE = 1 : Assuming 1000Base-T full duplex + * RTY = 0 : Disable retry test + * PEN = 1 : Pause frames disabled + * RXBUFO = 0 : No receive buffer offset + * LFERD = 0 : No length field error discard + * RFCS = 1 : Remove FCS + * CLK = 4 : Assuming MCK <= 160MHz + * DBW = 1 : 64-bit data bus with + * DCPF = 0 : Copy of pause frames not disabled + * RXCOEN = 0 : RX checksum offload disabled + * EFRHD = 0 : Disable frames received in half duple + * IRXFCS = 0 : Disable ignore RX FCX + * IPGSEN = 0 : IP stretch disabled + * RXBP = 0 : Receive bad pre-ambled disabled + * IRXER = 0 : Disable ignore IPG GXER */ - regval = sam_getreg(priv, SAM_GMAC_NCFGR); - regval |= (GMAC_NCFGR_RFCS | GMAC_NCFGR_PEN); + regval = GMAC_NCFGR_FD | GMAC_NCFGR_GBE | GMAC_NCFGR_PEN | + GMAC_NCFGR_RFCS | GMAC_NCFGR_CLK_DIV64 | GMAC_NCFGR_DBW_64; #ifdef CONFIG_NET_PROMISCUOUS - regval |= GMAC_NCFGR_CAF; -#else - regval &= ~GMAC_NCFGR_CAF; + regval |= GMAC_NCFGR_CAF; #endif #ifdef CONFIG_SAMA5_GMAC_NBC - regval |= GMAC_NCFGR_NBC; -#else - regval &= ~GMAC_NCFGR_NBC; + regval |= GMAC_NCFGR_NBC; #endif sam_putreg(priv, SAM_GMAC_NCFGR, regval); @@ -2889,9 +2896,12 @@ static int sam_gmac_configure(struct sam_gmac_s *priv) /* Setup the interrupts for TX events, RX events, and error events */ - regval = (GMAC_INT_RCOMP | GMAC_INT_RXUBR | GMAC_INT_TUR | GMAC_INT_RLEX | - GMAC_INT_TFC | GMAC_INT_TCOMP | GMAC_INT_ROVR | GMAC_INT_HRESP | - GMAC_INT_PFNZ | GMAC_INT_PTZ); + regval = GMAC_INT_MFS | GMAC_INT_RCOMP | GMAC_INT_RXUBR | GMAC_INT_TXUBR | + GMAC_INT_TUR | GMAC_INT_RLEX | GMAC_INT_TFC | GMAC_INT_TCOMP | + GMAC_INT_ROVR | GMAC_INT_HRESP | GMAC_INT_PFNZ | GMAC_INT_PTZ | + GMAC_INT_PFTR | GMAC_INT_EXINT | GMAC_INT_DRQFR | GMAC_INT_SFR | + GMAC_INT_DRQFT | GMAC_INT_SFT | GMAC_INT_PDRQFR | GMAC_INT_PDRSFR | + GMAC_INT_PDRQFT | GMAC_INT_PDRSFT; sam_putreg(priv, SAM_GMAC_IER, regval); return OK; } diff --git a/nuttx/include/nuttx/net/gmii.h b/nuttx/include/nuttx/net/gmii.h index 1b7f3b2bf..1161b22d5 100644 --- a/nuttx/include/nuttx/net/gmii.h +++ b/nuttx/include/nuttx/net/gmii.h @@ -64,16 +64,16 @@ #define GMII_EXPANSION MII_EXPANSION /* Auto-negotiation expansion */ #define GMII_NEXTPAGE MII_NEXTPAGE /* Auto-negotiation next page */ #define GMII_LPANEXTPAGE MII_LPANEXTPAGE /* Auto-negotiation link partner received next page */ -#define GMII_CTRL1000 9 /* 1000BASE-T control */ -#define GMII_STAT1000 10 /* 1000BASE-T status */ -#define GMII_PSECR 11 /* PSE Control register */ +#define GMII_1000BTCR 9 /* 1000BASE-T control */ +#define GMII_1000BTSR 10 /* 1000BASE-T status */ +#define GMII_ERCR 11 /* Extend Register - Control */ #define GMII_ERDWR 12 /* Extend Register - Data Write Register */ #define GMII_ERDRR 13 /* Extend Register - Data Read Register */ #define GMII_ESTATUS MII_ESTATUS /* Extended MII status register */ /* Extended Registers: Registers 16-31 may be used for vendor specific abilities */ -/* Micrel KSZ9021/31 Vendor Specific Registers */ +/* Micrel KSZ9021/31 Vendor Specific Register Addresses */ #define GMII_KSZ90x1_RLPBK 17 /* Remote loopback, LED mode */ #define GMII_KSZ90x1_LINKMD 18 /* LinkMD(c) cable diagnostic */ @@ -83,7 +83,7 @@ #define GMII_KSZ90x1_DBGCTRL1 28 /* Digital debug control 1 */ #define GMII_KSZ90x1_PHYCTRL 31 /* PHY control */ -/* Micrel KSZ9021/31 Extended registers */ +/* Micrel KSZ9021/31 Extended Register Addresses */ #define GMII_KSZ90x1_CCR 256 /* Common control */ #define GMII_KSZ90x1_SSR 257 /* Strap status */ @@ -130,9 +130,15 @@ /* MII ID2 register bits */ -#define GMII_PHYID2_OUI MII_PHYID2_OUI -#define GMII_PHYID2_MODEL MII_PHYID2_MODEL -#define GMII_PHYID2_REV MII_PHYID2_REV +#define GMII_PHYID2_REV_SHIFT MII_PHYID2_REV_SHIFT +#define GMII_PHYID2_REV_MASK MII_PHYID2_REV_MASK +#define GMII_PHYID2_REV(n) MII_PHYID2_REV(n) +#define GMII_PHYID2_MODEL_SHIFT MII_PHYID2_MODEL_SHIFT +#define GMII_PHYID2_MODEL_MASK MII_PHYID2_MODEL +# define GMII_PHYID2_MODEL(n) MII_PHYID2_MODEL(n) +#define GMII_PHYID2_OUI_SHIFT MII_PHYID2_OUI_SHIFT +#define GMII_PHYID2_OUI_MASK MII_PHYID2_OUI_MASK +# define GMII_PHYID2_OUI(n) MII_PHYID2_OUI(n) /* Advertisement control register bit definitions */ @@ -219,23 +225,48 @@ # define GMII_MMDCONTROL_FUNC_RWINCR MII_MMDCONTROL_FUNC_RWINCR # define GMII_MMDCONTROL_FUNC_WINCR MII_MMDCONTROL_FUNC_WINCR -/* Extended status register */ +/* Extended Status Register */ #define GMII_ESTATUS_1000BASETHALF MII_ESTATUS_1000BASETHALF #define GMII_ESTATUS_1000BASETFULL MII_ESTATUS_1000BASETFULL #define GMII_ESTATUS_1000BASEXHALF MII_ESTATUS_1000BASEXHALF #define GMII_ESTATUS_1000BASEXFULL MII_ESTATUS_1000BASEXFULL -/* Extend Register - Data Write Register */ - -#define GMII_ERDWR_ADDR_SHIFT (0) /* Bits 0-7: Select extended register address */ -#define GMII_ERDWR_ADDR_MASK (0xff << GMII_ERDWR_ADDR_SHIFT) -# define GMII_ERDWR_ADDR(n) ((n) << GMII_ERDWR_ADDR_SHIFT) -#define GMII_ERDWR_PAGE (1 << 8) /* Bit 8: Select page for extended register */ +/* 1000BASE-T Control Register */ + /* Bits 0-7: Reserved */ +#define GMII_1000BTCR_1000BASETHALF (1 << 8) /* Bit 8: 1000Base-T half duplex able */ +#define GMII_1000BTCR_1000BASETFULL (1 << 9) /* Bit 9: 1000Base-T full duplex able */ +#define GMII_1000BTCR_MULTIPLE (1 << 10) /* Bit 10: Port type: Prefer multiport device */ +#define GMII_1000BTCR_MMASTER (1 << 11) /* Bit 11: Configure PHY as master (manual) */ +#define GMII_1000BTCR_MSMC (1 << 12) /* Bit 12: Master/slave manual configuration */ +#define GMII_1000BTCR_TESTMODE_SHIFT (13) /* Bits 13-15: Test Mode */ +#define GMII_1000BTCR_TESTMODE_MASK (7 << GMII_1000BTCR_TESTMODE_SHIFT) +# define GMII_1000BTCR_MODE_NORMAL (0 << GMII_1000BTCR_TESTMODE_SHIFT) +# define GMII_1000BTCR_TESTMODE(n) ((n) << GMII_1000BTCR_TESTMODE_SHIFT) /* n=1-4 */ + +/* 1000BASE-T Status Register */ + +#define GMII_1000BTSR_IDLERR_SHIFT (0) /* Bits 0-7: Idle error count */ +#define GMII_1000BTSR_IDLERR_MASK (0xff << GMII_1000BTSR_IDLERR_SHIFT) + /* Bits 8-9: Reserved */ +#define GMII_1000BTSR_LP1000BASETHALF (1 << 10) /* Bit 10: Link partner 1000Base-T half duplex able */ +#define GMII_1000BTSR_LP1000BASETFULL (1 << 11) /* Bit 11: Link partner 1000Base-T full duplex able */ +#define GMII_1000BTSR_RROK (1 << 12) /* Bit 12: Remote receiver OK */ +#define GMII_1000BTSR_LROK (1 << 13) /* Bit 13: Local receiver OK */ +#define GMII_1000BTSR_MASTER (1 << 14) /* Bit 14: Configuration resolved to master */ +#define GMII_1000BTSR_MSFAULT (1 << 15) /* Bit 15: Master/slave fault detected */ + +/* Extend Register - Control Register */ + +#define GMII_ERCR_ADDR_SHIFT (0) /* Bits 0-7: Select extended register address */ +#define GMII_ERCR_ADDR_MASK (0xff << GMII_ERCR_ADDR_SHIFT) +# define GMII_ERCR_ADDR(n) ((n) << GMII_ERCR_ADDR_SHIFT) +#define GMII_ERCR_PAGE (1 << 8) /* Bit 8: Select page for extended register */ /* Bits 9-14: Reserved */ -#define GMII_ERDWR_READ (0) /* Bit 15: 0=Read extended register */ -#define GMII_ERDWR_WRITE (1 << 15) /* Bit 15: 1=Write extended register */ +#define GMII_ERCR_READ (0) /* Bit 15: 0=Read extended register */ +#define GMII_ERCR_WRITE (1 << 15) /* Bit 15: 1=Write extended register */ +/* Extend Register - Data Write Register (16-bit data value) */ /* Extend Register - Data Read Register (16-bit data value) */ /********************************************************************************************* diff --git a/nuttx/include/nuttx/net/mii.h b/nuttx/include/nuttx/net/mii.h index 411d51384..66d94e622 100644 --- a/nuttx/include/nuttx/net/mii.h +++ b/nuttx/include/nuttx/net/mii.h @@ -202,9 +202,15 @@ /* MII ID1 register bits: Bits 3-18 of the Organizationally Unique identifier (OUI) */ /* MII ID2 register bits */ -#define MII_PHYID2_OUI 0xfc00 /* Bits 10-15: OUI mask [24:19] */ -#define MII_PHYID2_MODEL 0x03f0 /* Bits 4-9: Model number mask */ -#define MII_PHYID2_REV 0x000f /* Bits 0-3: Revision number mask */ +#define MII_PHYID2_REV_SHIFT (0) /* Bits 0-3: Revision number mask */ +#define MII_PHYID2_REV_MASK (15 << MII_PHYID2_REV_SHIFT) +# define MII_PHYID2_REV(n) ((n) << MII_PHYID2_REV_SHIFT) +#define MII_PHYID2_MODEL_SHIFT (4) /* Bits 4-9: Model number mask */ +#define MII_PHYID2_MODEL_MASK (0x3f << MII_PHYID2_MODEL_SHIFT) +# define MII_PHYID2_MODEL(n) ((n) << MII_PHYID2_MODEL_SHIFT) +#define MII_PHYID2_OUI_SHIFT (10) /* Bits 10-15: OUI mask [24:19] */ +#define MII_PHYID2_OUI_MASK (0x3f << MII_PHYID2_OUI_SHIFT) +# define MII_PHYID2_OUI(n) ((n) << MII_PHYID2_OUI_SHIFT) /* Advertisement control register bit definitions */ -- cgit v1.2.3