From c807a6dc223f87fe2cef211e6684755e0f264be6 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 17 Sep 2013 10:55:13 -0600 Subject: SAMA5 EMAC: Resolve issues with DUAL PHY support needed for both EMAC and GMAC peripherals. EMAC driver is now code complete and builds without complaint --- nuttx/ChangeLog | 13 +++- nuttx/arch/arm/src/sama5/Kconfig | 30 ++++++- nuttx/arch/arm/src/sama5/Make.defs | 1 + nuttx/arch/arm/src/sama5/sam_emac.c | 133 +++++++++++++++----------------- nuttx/arch/arm/src/sama5/sam_ethernet.c | 11 +-- nuttx/arch/arm/src/stm32/Kconfig | 8 +- nuttx/arch/arm/src/stm32/stm32_eth.c | 6 +- 7 files changed, 113 insertions(+), 89 deletions(-) diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 52664213f..12b14d0df 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -5568,4 +5568,15 @@ * arch/arm/src/kl/chip/kl_pit.h and kp_tpm.h: Add register definitions for the Freescale Kinetis KL25Z from Alan Carvalho de Assis (2013-9-15). - + * configs/ and a few Ethernet drivers: Add the prefix ETH0 + to all PHY configuration selections. This will allow us + to support to Ethernet MAC drivers with two different + PHYS (identified with ETH0 and ETH1) (2013-9-17). + * net/Kconfig and drivers/net/Kconfig: Move PHY selections from + net/Kconfig to drivers/net/Kconfig where they belong. Add the previx + ETH0_ to each PHY selection. And a new configuration + CONFIG_NETDEV_MULTINIC that can be set to enable support for multiple + Ethernet MAC drivers (not fully implemented yet). When Enabled, + another set of PHY selections are enabled for ETH1_ (2013-9-17). + * include/nuttx/net/mii.h: Add definitions for the Micrel KSZ8051 PHY + (2013-9-17). diff --git a/nuttx/arch/arm/src/sama5/Kconfig b/nuttx/arch/arm/src/sama5/Kconfig index f161a27de..0e048c23b 100644 --- a/nuttx/arch/arm/src/sama5/Kconfig +++ b/nuttx/arch/arm/src/sama5/Kconfig @@ -159,11 +159,14 @@ config SAMA5_UDPHS config SAMA5_GMAC bool "Gigabit Ethernet MAC (GMAC)" default n + depends on SAMA5_HAVE_GMAC + select ARCH_HAVE_PHY config SAMA5_EMAC bool "10/100MBps Ethernet MAC (EMAC)" default n depends on SAMA5_HAVE_EMAC + select ARCH_HAVE_PHY config SAMA5_LCDC bool "LCD Controller (LCDC)" @@ -256,6 +259,20 @@ config SAMA5_HAVE_EMAC bool default n +if SAMA5_GMAC + +menu "GMAC device driver options" + +if SAMA5_EMAC + +config SAMA5_GMAC_ISETH0 + bool "GMAC is ETH0" + default y + +endif # SAMA5_EMAC +endmenu # GMAC device driver options +endif # SAMA5_GMAC + if SAMA5_EMAC menu "EMAC device driver options" @@ -398,28 +415,28 @@ config SAMA5_EMAC_PHYSR_ALTMODE for isolating the speed and full/half duplex mode bits. config SAMA5_EMAC_PHYSR_10HD - hex "10MHz/Half Duplex Value" + hex "10MBase-T Half Duplex Value" depends on SAMA5_EMAC_AUTONEG && SAMA5_EMAC_PHYSR_ALTCONFIG ---help--- This must be provided if SAMA5_EMAC_AUTONEG is defined. This is the value under the bit mask that represents the 10Mbps, half duplex setting. config SAMA5_EMAC_PHYSR_100HD - hex "100MHz/Half Duplex Value" + hex "100Base-T Half Duplex Value" depends on SAMA5_EMAC_AUTONEG && SAMA5_EMAC_PHYSR_ALTCONFIG ---help--- This must be provided if SAMA5_EMAC_AUTONEG is defined. This is the value under the bit mask that represents the 100Mbps, half duplex setting. config SAMA5_EMAC_PHYSR_10FD - hex "10MHz/Full Duplex Value" + hex "10Base-T Full Duplex Value" depends on SAMA5_EMAC_AUTONEG && SAMA5_EMAC_PHYSR_ALTCONFIG ---help--- This must be provided if SAMA5_EMAC_AUTONEG is defined. This is the value under the bit mask that represents the 10Mbps, full duplex setting. config SAMA5_EMAC_PHYSR_100FD - hex "100MHz/Full Duplex Value" + hex "100Base-T Full Duplex Value" depends on SAMA5_EMAC_AUTONEG && SAMA5_EMAC_PHYSR_ALTCONFIG ---help--- This must be provided if SAMA5_EMAC_AUTONEG is defined. This is the value @@ -432,6 +449,11 @@ config SAMA5_EMAC_REGDEBUG ---help--- Enable very low-level register access debug. Depends on DEBUG. +config SAMA5_EMAC_ISETH0 + bool + default y if !SAMA5_EMAC || !SAMA5_GMAC_ISETH0 + default n if SAMA5_EMAC && SAMA5_GMAC_ISETH0 + endmenu # EMAC device driver options endif # SAMA5_EMAC diff --git a/nuttx/arch/arm/src/sama5/Make.defs b/nuttx/arch/arm/src/sama5/Make.defs index dc78b023a..2d8e2baac 100644 --- a/nuttx/arch/arm/src/sama5/Make.defs +++ b/nuttx/arch/arm/src/sama5/Make.defs @@ -141,6 +141,7 @@ endif endif ifeq ($(CONFIG_NET),y) +CHIP_CSRCS += sam_ethernet.c ifeq ($(CONFIG_SAMA5_EMAC),y) CHIP_CSRCS += sam_emac.c endif diff --git a/nuttx/arch/arm/src/sama5/sam_emac.c b/nuttx/arch/arm/src/sama5/sam_emac.c index f56e6d681..cf957b2d0 100644 --- a/nuttx/arch/arm/src/sama5/sam_emac.c +++ b/nuttx/arch/arm/src/sama5/sam_emac.c @@ -47,7 +47,6 @@ ****************************************************************************/ #include -#if defined(CONFIG_NET) && defined(CONFIG_SAMA5_EMAC) #include #include @@ -79,6 +78,8 @@ #include +#if defined(CONFIG_NET) && defined(CONFIG_SAMA5_EMAC) + /**************************************************************************** * Definitions ****************************************************************************/ @@ -150,17 +151,42 @@ * REVISIT: net/Kconfig PHY definitions assume only a single Ethernet MAC. */ -#if defined(CONFIG_SAMA5_EMAC_PHY_DM9161) +#if defined(CONFIG_ETH0_PHY_DM9161) # define MII_OUI_MSB 0x0181 # define MII_OUI_LSB 0x2e -#elif defined(CONFIG_SAMA5_EMAC_PHY_LAN8700) +#elif defined(CONFIG_ETH0_PHY_LAN8700) # define MII_OUI_MSB 0x0007 # define MII_OUI_LSB 0x30 -#elif defined(CONFIG_SAMA5_EMAC_PHY_KSZ8051RNL) +#elif defined(CONFIG_ETH0_PHY_KSZ8051) # define MII_OUI_MSB 0x0022 # define MII_OUI_LSB 0x05 #else -# error No PHY Ethernet PHY defined +# error Ethernet PHY recognized +#endif + +#ifdef CONFIG_SAMA5_EMAC_PHYSR_ALTCONFIG + +# define PHYSR_MODE(sr) ((sr) & CONFIG_SAMA5_EMAC_PHYSR_ALTMODE) +# define PHYSR_ISMODE(sr,m) (PHYSR_MODE(sr) == (m)) + +# define PHYSR_IS10HDX(sr) PHYSR_ISMODE(sr,CONFIG_SAMA5_EMAC_PHYSR_10HD) +# define PHYSR_IS100HDX(sr) PHYSR_ISMODE(sr,CONFIG_SAMA5_EMAC_PHYSR_100HD) +# define PHYSR_IS10FDX(sr) PHYSR_ISMODE(sr,CONFIG_SAMA5_EMAC_PHYSR_10FD) +# define PHYSR_IS100FDX(sr) PHYSR_ISMODE(sr,CONFIG_SAMA5_EMAC_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 /* EMAC buffer sizes, number of buffers, and number of descriptors */ @@ -767,12 +793,11 @@ static int sam_uiptxpoll(struct uip_driver_s *dev) sam_transmit(priv); DEBUGASSERT(dev->d_len == 0 && dev->d_buf == NULL); - /* Check if the next TX descriptor is owned by the EMAC or CPU. We - * cannot perform the TX poll if we are unable to accept another packet for - * transmission. + /* Check if the there are any free TX descriptors. We cannot perform + * the TX poll if we do not have buffering for another packet. */ -#warning Missing logic + if (sam_txfree(priv) == 0) { /* We have to terminate the poll if we have no more descriptors * available for another transfer. @@ -810,12 +835,11 @@ static void sam_dopoll(struct sam_emac_s *priv) { struct uip_driver_s *dev = &priv->dev; - /* Check if the next TX descriptor is owned by the EMAC or - * CPU. We cannot perform the TX poll if we are unable to accept - * another packet for transmission. + /* Check if the there are any free TX descriptors. We cannot perform the + * TX poll if we do not have buffering for another packet. */ -#warning Missing logic + if (sam_txfree(priv) > 0) { /* If we have the descriptor, then poll uIP for new XMIT data. */ @@ -1194,7 +1218,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 | 0xffc300); nllvdbg("isr: %08x pending: %08x\n", isr, pending); /* Check for the receipt of an RX packet. @@ -1321,7 +1345,7 @@ static int sam_emac_interrupt(int irq, void *context) } #ifdef CONFIG_DEBUG_NET - /* Chekc for PAUSE Frame recieved (PFRE). + /* Check for PAUSE Frame recieved (PFRE). * * ISR:PFRE indicates that a pause frame has been received. Cleared on a read. */ @@ -1405,12 +1429,11 @@ static void sam_polltimer(int argc, uint32_t arg, ...) struct sam_emac_s *priv = (struct sam_emac_s *)arg; struct uip_driver_s *dev = &priv->dev; - /* Check if the next TX descriptor is owned by the EMAC or CPU. We - * cannot perform the timer poll if we are unable to accept another packet - * for transmission. Hmmm.. might be bug here. Does this mean if there is - * a transmit in progress, we will miss TCP time state updates? + /* Check if the there are any free TX descriptors. We cannot perform the + * TX poll if we do not have buffering for another packet. */ -#warning Missing logic + + if (sam_txfree(priv) > 0) { /* Update TCP timing states and poll uIP for new XMIT data. */ @@ -1684,33 +1707,15 @@ static void sam_phydump(struct sam_emac_s *priv) #endif sam_phyread(priv, priv->phyaddr, MII_MCR, &value); - nllvdbg(" BMCR: %04x\n", value); + nllvdbg(" MCR: %04x\n", value); sam_phyread(priv, priv->phyaddr, MII_MSR, &value); - nllvdbg(" BMSR: %04x\n", value); + nllvdbg(" MSR: %04x\n", value); sam_phyread(priv, priv->phyaddr, MII_ADVERTISE, &value); - nllvdbg(" ANAR: %04x\n", value); + nllvdbg(" ADVERTISE: %04x\n", value); sam_phyread(priv, priv->phyaddr, MII_LPA, &value); - nllvdbg(" ANLPAR: %04x\n", value); - sam_phyread(priv, priv->phyaddr, MII_ANER, &value); - nllvdbg(" ANER: %04x\n", value); - sam_phyread(priv, priv->phyaddr, MII_DSCR, &value); - nllvdbg(" DSCR: %04x\n", value); - sam_phyread(priv, priv->phyaddr, MII_DSCSR, &value); - nllvdbg(" DSCSR: %04x\n", value); - sam_phyread(priv, priv->phyaddr, MII_10BTCSR, &value); - nllvdbg(" 10BTCSR: %04x\n", value); - sam_phyread(priv, priv->phyaddr, MII_PWDOR, &value); - nllvdbg(" PWDOR: %04x\n", value); - sam_phyread(priv, priv->phyaddr, MII_CONFIGR, &value); - nllvdbg(" CONFIGR: %04x\n", value); - sam_phyread(priv, priv->phyaddr, MII_MDINTR, &value); - nllvdbg(" MDINTR: %04x\n", value); - sam_phyread(priv, priv->phyaddr, MII_RECR, &value); - nllvdbg(" RECR: %04x\n", value); - sam_phyread(priv, priv->phyaddr, MII_DISCR, &value); - nllvdbg(" DISCR: %04x\n", value); - sam_phyread(priv, priv->phyaddr, MII_RLSR, &value); - nllvdbg(" RLSR: %04x\n", value); + nllvdbg(" LPR: %04x\n", value); + sam_phyread(priv, priv->phyaddr, CONFIG_SAMA5_EMAC_PHYSR, &value); + nllvdbg(" PHYSR: %04x\n", value); /* Disable management port */ @@ -1888,10 +1893,10 @@ static int sam_phyfind(struct sam_emac_s *priv, uint8_t *phyaddr) if (ret == OK) { - nllvdbg("PHYID1: %04x PHY addr: %d\n", value, candidate); + nllvdbg(" PHYID1: %04x PHY addr: %d\n", value, candidate); *phyaddr = candidate; - sam_phyread(priv, candidate, MII_DSCSR, &value); - nllvdbg("DSCSR: %04x PHY addr: %d\n", value, candidate); + sam_phyread(priv, candidate, CONFIG_SAMA5_EMAC_PHYSR, &value); + nllvdbg(" PHYSR: %04x PHY addr: %d\n", value, candidate); } /* Disable management port */ @@ -2253,7 +2258,7 @@ static bool sam_linkup(struct sam_emac_s *priv) { uint32_t regval; uint16_t msr; - uint16_t dscsr; + uint16_t physr; bool linkup = false; int ret; @@ -2278,30 +2283,30 @@ static bool sam_linkup(struct sam_emac_s *priv) /* Re-configure Link speed */ - ret = sam_phyread(priv, priv->phyaddr, MII_DSCSR, &dscsr); + ret = sam_phyread(priv, priv->phyaddr, CONFIG_SAMA5_EMAC_PHYSR, &physr); if (ret < 0) { - nlldbg("ERROR: Failed to read DSCSR: %d\n", ret); + nlldbg("ERROR: Failed to read PHYSR: %d\n", ret); goto errout; } regval = sam_getreg(priv, SAM_EMAC_NCFGR); regval &= ~(EMAC_NCFGR_SPD | EMAC_NCFGR_FD); - if ((msr & MII_MSR_100BASETXFULL) && (dscsr & MII_DSCSR_100FDX)) + if ((msr & MII_MSR_100BASETXFULL) != 0 && PHYSR_IS100FDX(physr)) { /* Set EMAC for 100BaseTX and Full Duplex */ regval |= (EMAC_NCFGR_SPD | EMAC_NCFGR_FD); } - else if ((msr & MII_MSR_10BASETXFULL) && (dscsr & MII_DSCSR_10FDX)) + else if ((msr & MII_MSR_10BASETXFULL) != 0 && PHYSR_IS10FDX(physr)) { /* Set MII for 10BaseT and Full Duplex */ regval |= EMAC_NCFGR_FD; } - else if ((msr & MII_MSR_100BASETXHALF) && (dscsr & MII_DSCSR_100HDX)) + else if ((msr & MII_MSR_100BASETXHALF) != 0 && PHYSR_IS100HDX(physr)) { /* Set MII for 100BaseTX and Half Duplex */ @@ -2309,7 +2314,7 @@ static bool sam_linkup(struct sam_emac_s *priv) } #if 0 - else if ((msr & MII_MSR_10BASETXHALF) && (dscsr & MII_DSCSR_10HDX)) + else if ((msr & MII_MSR_10BASETXHALF) != 0 && PHYSR_IS10HDX(physr)) { /* Set MII for 10BaseT and Half Duplex */ } @@ -2413,30 +2418,12 @@ static inline void sam_ethgpioconfig(struct sam_emac_s *priv) sam_configpio(PIO_EMAC_TX1); sam_configpio(PIO_EMAC_RX0); sam_configpio(PIO_EMAC_RX1); - sam_configpio(PIO_EMAC_TXEN); sam_configpio(PIO_EMAC_CRSDV); sam_configpio(PIO_EMAC_RXER); sam_configpio(PIO_EMAC_REFCK); - - /* MDC and MDIO are common to both modes */ - sam_configpio(PIO_EMAC_MDC); sam_configpio(PIO_EMAC_MDIO); - -#if defined(CONFIG_SAMA5_EMAC_MII) - /* Provide clocking for the MII interface */ -#warning Missing logic - -# endif - - /* Set up the RMII interface. */ - -#elif defined(CONFIG_SAMA5_EMAC_RMII) - /* Provide clocking for the RMII interface */ -#warning Missing logic - -#endif } /**************************************************************************** @@ -2837,3 +2824,5 @@ errout_with_txpoll: errout: return ret; } + +#endif /* CONFIG_NET && CONFIG_SAMA5_EMAC */ diff --git a/nuttx/arch/arm/src/sama5/sam_ethernet.c b/nuttx/arch/arm/src/sama5/sam_ethernet.c index 5e938523d..cbf91d5f3 100644 --- a/nuttx/arch/arm/src/sama5/sam_ethernet.c +++ b/nuttx/arch/arm/src/sama5/sam_ethernet.c @@ -38,13 +38,14 @@ ****************************************************************************/ #include + #include #include "sam_ethernet.h" #ifdef CONFIG_NET /**************************************************************************** - * Definitions + * Pre-processor Definitions ****************************************************************************/ /**************************************************************************** @@ -88,6 +89,9 @@ void up_netinitialize(void) { +#if defined(CONFIG_SAMA5_GMAC) || defined(CONFIG_SAMA5_EMAC) + int ret; + /* Initialize the GMAC driver */ #ifdef CONFIG_SAMA5_GMAC @@ -95,7 +99,6 @@ void up_netinitialize(void) if (ret < 0) { nlldbg("ERROR: sam_gmac_initialize failed: %d\n", ret); - return ret; } #endif @@ -106,11 +109,9 @@ void up_netinitialize(void) if (ret < 0) { nlldbg("ERROR: sam_gmac_initialize failed: %d\n", ret); - return ret; } #endif - - return OK; +#endif /* CONFIG_SAMA5_GMAC | CONFIG_SAMA5_EMAC */ } #endif /* CONFIG_NET && CONFIG_SAMA5_EMAC */ diff --git a/nuttx/arch/arm/src/stm32/Kconfig b/nuttx/arch/arm/src/stm32/Kconfig index 3708b9e7b..e9c5a2bba 100644 --- a/nuttx/arch/arm/src/stm32/Kconfig +++ b/nuttx/arch/arm/src/stm32/Kconfig @@ -2728,28 +2728,28 @@ config STM32_PHYSR_ALTMODE for isolating the speed and full/half duplex mode bits. config STM32_PHYSR_10HD - hex "10MHz/Half Duplex Value" + hex "10MBase-T Half Duplex Value" depends on STM32_AUTONEG && STM32_PHYSR_ALTCONFIG ---help--- This must be provided if STM32_AUTONEG is defined. This is the value under the bit mask that represents the 10Mbps, half duplex setting. config STM32_PHYSR_100HD - hex "100MHz/Half Duplex Value" + hex "100Base-T Half Duplex Value" depends on STM32_AUTONEG && STM32_PHYSR_ALTCONFIG ---help--- This must be provided if STM32_AUTONEG is defined. This is the value under the bit mask that represents the 100Mbps, half duplex setting. config STM32_PHYSR_10FD - hex "10MHz/Full Duplex Value" + hex "10Base-T Full Duplex Value" depends on STM32_AUTONEG && STM32_PHYSR_ALTCONFIG ---help--- This must be provided if STM32_AUTONEG is defined. This is the value under the bit mask that represents the 10Mbps, full duplex setting. config STM32_PHYSR_100FD - hex "100MHz/Full Duplex Value" + hex "100Base-T Full Duplex Value" depends on STM32_AUTONEG && STM32_PHYSR_ALTCONFIG ---help--- This must be provided if STM32_AUTONEG is defined. This is the value diff --git a/nuttx/arch/arm/src/stm32/stm32_eth.c b/nuttx/arch/arm/src/stm32/stm32_eth.c index c61ea1f7c..2e9fc4081 100644 --- a/nuttx/arch/arm/src/stm32/stm32_eth.c +++ b/nuttx/arch/arm/src/stm32/stm32_eth.c @@ -664,7 +664,7 @@ static void stm32_rxdescinit(FAR struct stm32_ethmac_s *priv); static int stm32_phyread(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t *value); static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t value); -#ifdef CONFIG_PHY_DM9161 +#ifdef CONFIG_ETH0_PHY_DM9161 static inline int stm32_dm9161(FAR struct stm32_ethmac_s *priv); #endif static int stm32_phyinit(FAR struct stm32_ethmac_s *priv); @@ -2501,7 +2501,7 @@ static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr, uint16_t val * ****************************************************************************/ -#ifdef CONFIG_PHY_DM9161 +#ifdef CONFIG_ETH0_PHY_DM9161 static inline int stm32_dm9161(FAR struct stm32_ethmac_s *priv) { uint16_t phyval; @@ -2607,7 +2607,7 @@ static int stm32_phyinit(FAR struct stm32_ethmac_s *priv) /* Special workaround for the Davicom DM9161 PHY is required. */ -#ifdef CONFIG_PHY_DM9161 +#ifdef CONFIG_ETH0_PHY_DM9161 ret = stm32_dm9161(priv); if (ret < 0) { -- cgit v1.2.3