Beginng of support for GMII/RGMII PHYs

This commit is contained in:
Gregory Nutt 2013-09-26 15:55:21 -06:00
parent 48f1227fbf
commit fbd09bd75f
5 changed files with 229 additions and 145 deletions

View File

@ -277,7 +277,7 @@ config SAMA5_GMAC_NRXBUFFERS
config SAMA5_GMAC_NTXBUFFERS config SAMA5_GMAC_NTXBUFFERS
int "Number of TX buffers" int "Number of TX buffers"
default 1 default 8
---help--- ---help---
GMAC buffer memory is segmented into full Ethernet packets (size GMAC buffer memory is segmented into full Ethernet packets (size
NET_BUFSIZE bytes). This setting provides the number of such packets NET_BUFSIZE bytes). This setting provides the number of such packets
@ -471,7 +471,7 @@ config SAMA5_EMAC_NRXBUFFERS
config SAMA5_EMAC_NTXBUFFERS config SAMA5_EMAC_NTXBUFFERS
int "Number of TX buffers" int "Number of TX buffers"
default 1 default 8
---help--- ---help---
EMAC buffer memory is segmented into full Ethernet packets (size EMAC buffer memory is segmented into full Ethernet packets (size
NET_BUFSIZE bytes). This setting provides the number of such packets NET_BUFSIZE bytes). This setting provides the number of such packets

View File

@ -483,7 +483,7 @@
# define GMAC_NCFGR_CLK_DIV32 (2 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 32 (MCK up to 80 MHz) */ # define GMAC_NCFGR_CLK_DIV32 (2 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 32 (MCK up to 80 MHz) */
# define GMAC_NCFGR_CLK_DIV48 (3 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 48 (MCK up to 120 MHz) */ # define GMAC_NCFGR_CLK_DIV48 (3 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 48 (MCK up to 120 MHz) */
# define GMAC_NCFGR_CLK_DIV64 (4 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 64 (MCK up to 160 MHz) */ # define GMAC_NCFGR_CLK_DIV64 (4 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 64 (MCK up to 160 MHz) */
# define GMAC_NCFGR_CLK_DIV96 (5 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 64 (MCK up to 240 MHz) */ # define GMAC_NCFGR_CLK_DIV96 (5 << GMAC_NCFGR_CLK_SHIFT) /* MCK divided by 96 (MCK up to 240 MHz) */
#define GMAC_NCFGR_DBW_SHIFT (21) /* Bits 21-22: Data Bus Width */ #define GMAC_NCFGR_DBW_SHIFT (21) /* Bits 21-22: Data Bus Width */
#define GMAC_NCFGR_DBW_MASK (3 << GMAC_NCFGR_DBW_SHIFT) #define GMAC_NCFGR_DBW_MASK (3 << GMAC_NCFGR_DBW_SHIFT)
# define GMAC_NCFGR_DBW_32 (0 << GMAC_NCFGR_DBW_SHIFT) /* 32-bit data bus width */ # define GMAC_NCFGR_DBW_32 (0 << GMAC_NCFGR_DBW_SHIFT) /* 32-bit data bus width */

View File

@ -94,7 +94,7 @@
/* Number of buffer for TX */ /* Number of buffer for TX */
#ifndef CONFIG_SAMA5_EMAC_NTXBUFFERS #ifndef CONFIG_SAMA5_EMAC_NTXBUFFERS
# define CONFIG_SAMA5_EMAC_NTXBUFFERS 32 # define CONFIG_SAMA5_EMAC_NTXBUFFERS 8
#endif #endif
#undef CONFIG_SAMA5_EMAC_NBC #undef CONFIG_SAMA5_EMAC_NBC
@ -294,11 +294,13 @@ static struct sam_emac_s g_emac;
/* Preallocated data */ /* Preallocated data */
/* TX descriptors list */ /* TX descriptors list */
static struct emac_txdesc_s g_txdesc[TX_BUFFERS] __attribute__((aligned(8))); static struct emac_txdesc_s g_txdesc[CONFIG_SAMA5_EMAC_NTXBUFFERS]
__attribute__((aligned(8)));
/* RX descriptors list */ /* RX descriptors list */
static struct emac_rxdesc_s g_rxdesc[RX_BUFFERS]__attribute__((aligned(8))); static struct emac_rxdesc_s g_rxdesc[CONFIG_SAMA5_EMAC_NRXBUFFERS]
__attribute__((aligned(8)));
/* Transmit Buffers /* Transmit Buffers
* *

View File

@ -75,6 +75,8 @@
# define SAMA5_GMAC_PHY_LAN8700 1 # define SAMA5_GMAC_PHY_LAN8700 1
# elif defined(CONFIG_ETH0_PHY_KSZ8051) # elif defined(CONFIG_ETH0_PHY_KSZ8051)
# define SAMA5_GMAC_PHY_KSZ8051 1 # define SAMA5_GMAC_PHY_KSZ8051 1
# elif defined(CONFIG_ETH0_PHY_KSZ90x1)
# define SAMA5_GMAC_PHY_KSZ90x1 1
# else # else
# error ETH0 PHY unrecognized # error ETH0 PHY unrecognized
# endif # endif
@ -85,6 +87,8 @@
# define SAMA5_GMAC_PHY_LAN8700 1 # define SAMA5_GMAC_PHY_LAN8700 1
# elif defined(CONFIG_ETH1_PHY_KSZ8051) # elif defined(CONFIG_ETH1_PHY_KSZ8051)
# define SAMA5_GMAC_PHY_KSZ8051 1 # define SAMA5_GMAC_PHY_KSZ8051 1
# elif defined(CONFIG_ETH1_PHY_KSZ90x1)
# define SAMA5_GMAC_PHY_KSZ90x1 1
# else # else
# error ETH1 PHY unrecognized # error ETH1 PHY unrecognized
# endif # endif
@ -97,6 +101,8 @@
# define SAMA5_EMAC_PHY_LAN8700 1 # define SAMA5_EMAC_PHY_LAN8700 1
# elif defined(CONFIG_ETH0_PHY_KSZ8051) # elif defined(CONFIG_ETH0_PHY_KSZ8051)
# define SAMA5_EMAC_PHY_KSZ8051 1 # define SAMA5_EMAC_PHY_KSZ8051 1
# elif defined(CONFIG_ETH0_PHY_KSZ90x1)
# define SAMA5_EMAC_PHY_KSZ90x1 1
# else # else
# error ETH0 PHY unrecognized # error ETH0 PHY unrecognized
# endif # endif
@ -107,6 +113,8 @@
# define SAMA5_EMAC_PHY_LAN8700 1 # define SAMA5_EMAC_PHY_LAN8700 1
# elif defined(CONFIG_ETH1_PHY_KSZ8051) # elif defined(CONFIG_ETH1_PHY_KSZ8051)
# define SAMA5_EMAC_PHY_KSZ8051 1 # define SAMA5_EMAC_PHY_KSZ8051 1
# elif defined(CONFIG_ETH1_PHY_KSZ90x1)
# define SAMA5_EMAC_PHY_KSZ90x1 1
# else # else
# error ETH1 PHY unrecognized # error ETH1 PHY unrecognized
# endif # endif

View File

@ -60,7 +60,7 @@
#include <nuttx/irq.h> #include <nuttx/irq.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <nuttx/net/mii.h> #include <nuttx/net/gmii.h>
#include <nuttx/net/uip/uip.h> #include <nuttx/net/uip/uip.h>
#include <nuttx/net/uip/uip-arp.h> #include <nuttx/net/uip/uip-arp.h>
#include <nuttx/net/uip/uip-arch.h> #include <nuttx/net/uip/uip-arch.h>
@ -94,7 +94,7 @@
/* Number of buffer for TX */ /* Number of buffer for TX */
#ifndef CONFIG_SAMA5_GMAC_NTXBUFFERS #ifndef CONFIG_SAMA5_GMAC_NTXBUFFERS
# define CONFIG_SAMA5_GMAC_NTXBUFFERS 32 # define CONFIG_SAMA5_GMAC_NTXBUFFERS 8
#endif #endif
#undef CONFIG_SAMA5_GMAC_NBC #undef CONFIG_SAMA5_GMAC_NBC
@ -149,17 +149,11 @@
/* PHY definitions */ /* PHY definitions */
#if defined(SAMA5_GMAC_PHY_DM9161) #ifdef SAMA5_GMAC_PHY_KSZ90x1
# define MII_OUI_MSB 0x0181 # define GMII_OUI_MSB 0x0022
# define MII_OUI_LSB 0x2e # define GMII_OUI_LSB 0x05
#elif defined(SAMA5_GMAC_PHY_LAN8700)
# define MII_OUI_MSB 0x0007
# define MII_OUI_LSB 0x30
#elif defined(SAMA5_GMAC_PHY_KSZ8051)
# define MII_OUI_MSB 0x0022
# define MII_OUI_LSB 0x05
#else #else
# error GMAC PHY unrecognized # error Unknown PHY
#endif #endif
#ifdef CONFIG_SAMA5_GMAC_PHYSR_ALTCONFIG #ifdef CONFIG_SAMA5_GMAC_PHYSR_ALTCONFIG
@ -203,6 +197,13 @@
#define GMAC_RX_UNITSIZE 128 /* Fixed size for RX buffer */ #define GMAC_RX_UNITSIZE 128 /* Fixed size for RX buffer */
#define GMAC_TX_UNITSIZE CONFIG_NET_BUFSIZE /* MAX size for Ethernet packet */ #define GMAC_TX_UNITSIZE CONFIG_NET_BUFSIZE /* MAX size for Ethernet packet */
/* The MAC can support frame lengths up to 1536 bytes */
#define GMAC_MAX_FRAMELEN 1536
#if CONFIG_NET_BUFSIZE >GMAC_MAX_FRAMELEN
# error CONFIG_NET_BUFSIZE is too large
#endif
/* We need at least one more free buffer than transmit buffers */ /* We need at least one more free buffer than transmit buffers */
#define SAM_GMAC_NFREEBUFFERS (CONFIG_SAMA5_GMAC_NTXBUFFERS+1) #define SAM_GMAC_NFREEBUFFERS (CONFIG_SAMA5_GMAC_NTXBUFFERS+1)
@ -235,7 +236,7 @@
/* PHY read/write delays in loop counts */ /* PHY read/write delays in loop counts */
#define PHY_RETRY_MAX 1000000 #define PHY_RETRY_MAX 300000
/* Helpers ******************************************************************/ /* Helpers ******************************************************************/
/* This is a helper pointer for accessing the contents of the GMAC /* This is a helper pointer for accessing the contents of the GMAC
@ -294,11 +295,13 @@ static struct sam_gmac_s g_gmac;
/* Preallocated data */ /* Preallocated data */
/* TX descriptors list */ /* TX descriptors list */
static struct gmac_txdesc_s g_txdesc[TX_BUFFERS] __attribute__((aligned(8))); static struct gmac_txdesc_s g_txdesc[CONFIG_SAMA5_GMAC_NTXBUFFERS]
__attribute__((aligned(8)));
/* RX descriptors list */ /* RX descriptors list */
static struct gmac_rxdesc_s g_rxdesc[RX_BUFFERS]__attribute__((aligned(8))); static struct gmac_rxdesc_s g_rxdesc[CONFIG_SAMA5_GMAC_NRXBUFFERS]
__attribute__((aligned(8)));
/* Transmit Buffers /* Transmit Buffers
* *
@ -307,14 +310,13 @@ static struct gmac_rxdesc_s g_rxdesc[RX_BUFFERS]__attribute__((aligned(8)));
* shall be set to 0 * shall be set to 0
*/ */
static uint8_t g_txbuffer[CONFIG_SAMA5_GMAC_NTXBUFFERS * GMAC_TX_UNITSIZE]; static uint8_t g_txbuffer[CONFIG_SAMA5_GMAC_NTXBUFFERS * GMAC_TX_UNITSIZE]
__attribute__((aligned(8))) __attribute__((aligned(8)));
/* Receive Buffers */ /* Receive Buffers */
static uint8_t g_rxbuffer[CONFIG_SAMA5_GMAC_NRXBUFFERS * GMAC_RX_UNITSIZE] static uint8_t g_rxbuffer[CONFIG_SAMA5_GMAC_NRXBUFFERS * GMAC_RX_UNITSIZE]
__attribute__((aligned(8))); __attribute__((aligned(8)));
#endif #endif
/**************************************************************************** /****************************************************************************
@ -384,6 +386,7 @@ static int sam_phywrite(struct sam_gmac_s *priv, uint8_t phyaddr,
uint8_t regaddr, uint16_t phyval); uint8_t regaddr, uint16_t phyval);
static int sam_autonegotiate(struct sam_gmac_s *priv); static int sam_autonegotiate(struct sam_gmac_s *priv);
static bool sam_linkup(struct sam_gmac_s *priv); static bool sam_linkup(struct sam_gmac_s *priv);
static void sam_mdcclock(struct sam_gmac_s *priv);
static int sam_phyinit(struct sam_gmac_s *priv); static int sam_phyinit(struct sam_gmac_s *priv);
/* GMAC Initialization */ /* GMAC Initialization */
@ -1786,9 +1789,7 @@ static void sam_phydump(struct sam_gmac_s *priv)
/* Enable management port */ /* Enable management port */
regval = sam_getreg(priv, SAM_GMAC_NCR); sam_enablemdio(priv);
regval |= GMAC_NCR_MPE;
sam_putreg(priv, SAM_GMAC_NCR, regval);
#ifdef CONFIG_SAMA5_GMAC_RGMII #ifdef CONFIG_SAMA5_GMAC_RGMII
nllvdbg("RMII Registers (Address %02x)\n", priv->phyaddr); nllvdbg("RMII Registers (Address %02x)\n", priv->phyaddr);
@ -1796,25 +1797,89 @@ static void sam_phydump(struct sam_gmac_s *priv)
nllvdbg("MII Registers (Address %02x)\n", priv->phyaddr); nllvdbg("MII Registers (Address %02x)\n", priv->phyaddr);
#endif #endif
sam_phyread(priv, priv->phyaddr, MII_MCR, &phyval); sam_phyread(priv, priv->phyaddr, GMII_MCR, &phyval);
nllvdbg(" MCR: %04x\n", phyval); nllvdbg(" MCR: %04x\n", phyval);
sam_phyread(priv, priv->phyaddr, MII_MSR, &phyval); sam_phyread(priv, priv->phyaddr, GMII_MSR, &phyval);
nllvdbg(" MSR: %04x\n", phyval); nllvdbg(" MSR: %04x\n", phyval);
sam_phyread(priv, priv->phyaddr, MII_ADVERTISE, &phyval); sam_phyread(priv, priv->phyaddr, GMII_ADVERTISE, &phyval);
nllvdbg(" ADVERTISE: %04x\n", phyval); nllvdbg(" ADVERTISE: %04x\n", phyval);
sam_phyread(priv, priv->phyaddr, MII_LPA, &phyval); sam_phyread(priv, priv->phyaddr, GMII_LPA, &phyval);
nllvdbg(" LPR: %04x\n", phyval); nllvdbg(" LPR: %04x\n", phyval);
sam_phyread(priv, priv->phyaddr, CONFIG_SAMA5_GMAC_PHYSR, &phyval); sam_phyread(priv, priv->phyaddr, CONFIG_SAMA5_GMAC_PHYSR, &phyval);
nllvdbg(" PHYSR: %04x\n", phyval); nllvdbg(" PHYSR: %04x\n", phyval);
/* Disable management port */ /* Disable management port */
regval = sam_getreg(priv, SAM_GMAC_NCR); sam_disablemdio(priv);
regval &= ~GMAC_NCR_MPE;
sam_putreg(priv, SAM_GMAC_NCR, regval);
} }
#endif #endif
/****************************************************************************
* Function: sam_enablemdio
*
* Description:
* Enable the management port
*
* Parameters:
* priv - A reference to the private driver state structure
*
* Returned Value:
* None
*
****************************************************************************/
static void sam_enablemdio(struct sam_gmac_s *priv)
{
uint32_t regval;
uint32_t enables;
/* Enable management port */
regval = sam_getreg(priv, SAM_GMAC_NCR);
enables = regval & (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
regval &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
regval |= GMAC_NCR_MPE;
sam_putreg(priv, SAM_GMAC_NCR, regval);
regval |= enables;
sam_putreg(priv, SAM_GMAC_NCR, regval);
}
/****************************************************************************
* Function: sam_disablemdio
*
* Description:
* Disable the management port
*
* Parameters:
* priv - A reference to the private driver state structure
*
* Returned Value:
* None
*
****************************************************************************/
static void sam_disablemdio(struct sam_gmac_s *priv)
{
uint32_t regval;
uint32_t enables;
/* Disable management port */
regval = sam_getreg(priv, SAM_GMAC_NCR);
enables = regval & (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
regval &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
sam_putreg(priv, SAM_GMAC_NCR, regval);
regval &= ~GMAC_NCR_MPE;
sam_putreg(priv, SAM_GMAC_NCR, regval);
regval |= enables;
sam_putreg(priv, SAM_GMAC_NCR, regval);
}
/**************************************************************************** /****************************************************************************
* Function: sam_phywait * Function: sam_phywait
* *
@ -1866,7 +1931,6 @@ static int sam_phywait(struct sam_gmac_s *priv)
static int sam_phyreset(struct sam_gmac_s *priv) static int sam_phyreset(struct sam_gmac_s *priv)
{ {
uint32_t regval;
uint16_t mcr; uint16_t mcr;
int timeout; int timeout;
int ret; int ret;
@ -1875,13 +1939,11 @@ static int sam_phyreset(struct sam_gmac_s *priv)
/* Enable management port */ /* Enable management port */
regval = sam_getreg(priv, SAM_GMAC_NCR); sam_enablemdio(priv);
regval |= GMAC_NCR_MPE;
sam_putreg(priv, SAM_GMAC_NCR, regval);
/* Reset the PHY */ /* Reset the PHY */
ret = sam_phywrite(priv, priv->phyaddr, MII_MCR, MII_MCR_RESET); ret = sam_phywrite(priv, priv->phyaddr, GMII_MCR, GMII_MCR_RESET);
if (ret < 0) if (ret < 0)
{ {
nlldbg("ERROR: sam_phywrite failed: %d\n", ret); nlldbg("ERROR: sam_phywrite failed: %d\n", ret);
@ -1892,14 +1954,14 @@ static int sam_phyreset(struct sam_gmac_s *priv)
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
for (timeout = 0; timeout < 10; timeout++) for (timeout = 0; timeout < 10; timeout++)
{ {
mcr = MII_MCR_RESET; mcr = GMII_MCR_RESET;
int result = sam_phyread(priv, priv->phyaddr, MII_MCR, &mcr); int result = sam_phyread(priv, priv->phyaddr, GMII_MCR, &mcr);
if (result < 0) if (result < 0)
{ {
nlldbg("ERROR: Failed to read the MCR register: %d\n", ret); nlldbg("ERROR: Failed to read the MCR register: %d\n", ret);
ret = result; ret = result;
} }
else if ((mcr & MII_MCR_RESET) == 0) else if ((mcr & GMII_MCR_RESET) == 0)
{ {
ret = OK; ret = OK;
break; break;
@ -1908,9 +1970,7 @@ static int sam_phyreset(struct sam_gmac_s *priv)
/* Disable management port */ /* Disable management port */
regval = sam_getreg(priv, SAM_GMAC_NCR); sam_disablemdio(priv);
regval &= ~GMAC_NCR_MPE;
sam_putreg(priv, SAM_GMAC_NCR, regval);
return ret; return ret;
} }
@ -1932,7 +1992,6 @@ static int sam_phyreset(struct sam_gmac_s *priv)
static int sam_phyfind(struct sam_gmac_s *priv, uint8_t *phyaddr) static int sam_phyfind(struct sam_gmac_s *priv, uint8_t *phyaddr)
{ {
uint32_t regval;
uint16_t phyval; uint16_t phyval;
uint8_t candidate; uint8_t candidate;
unsigned int offset; unsigned int offset;
@ -1942,16 +2001,14 @@ static int sam_phyfind(struct sam_gmac_s *priv, uint8_t *phyaddr)
/* Enable management port */ /* Enable management port */
regval = sam_getreg(priv, SAM_GMAC_NCR); sam_enablemdio(priv);
regval |= GMAC_NCR_MPE;
sam_putreg(priv, SAM_GMAC_NCR, regval); /* Check initial candidate address */
candidate = *phyaddr; candidate = *phyaddr;
/* Check current candidate address */ ret = sam_phyread(priv, candidate, GMII_PHYID1, &phyval);
if (ret == OK && phyval == GMII_OUI_MSB)
ret = sam_phyread(priv, candidate, MII_PHYID1, &phyval);
if (ret == OK && phyval == MII_OUI_MSB)
{ {
*phyaddr = candidate; *phyaddr = candidate;
ret = OK; ret = OK;
@ -1972,8 +2029,8 @@ static int sam_phyfind(struct sam_gmac_s *priv, uint8_t *phyaddr)
/* Try reading the PHY ID from the candidate PHY address */ /* Try reading the PHY ID from the candidate PHY address */
ret = sam_phyread(priv, candidate, MII_PHYID1, &phyval); ret = sam_phyread(priv, candidate, GMII_PHYID1, &phyval);
if (ret == OK && phyval == MII_OUI_MSB) if (ret == OK && phyval == GMII_OUI_MSB)
{ {
ret = OK; ret = OK;
break; break;
@ -1991,9 +2048,7 @@ static int sam_phyfind(struct sam_gmac_s *priv, uint8_t *phyaddr)
/* Disable management port */ /* Disable management port */
regval = sam_getreg(priv, SAM_GMAC_NCR); sam_disablemdio(priv);
regval &= ~GMAC_NCR_MPE;
sam_putreg(priv, SAM_GMAC_NCR, regval);
return ret; return ret;
} }
@ -2034,7 +2089,7 @@ static int sam_phyread(struct sam_gmac_s *priv, uint8_t phyaddr,
/* Write the PHY Maintenance register */ /* Write the PHY Maintenance register */
regval = GMAC_MAN_DATA(0) | GMAC_MAN_WTN | GMAC_MAN_REGA(regaddr) | regval = GMAC_MAN_DATA(0) | GMAC_MAN_WTN | GMAC_MAN_REGA(regaddr) |
GMAC_MAN_PHYA(priv->phyaddr) | GMAC_MAN_READ; GMAC_MAN_PHYA(priv->phyaddr) | GMAC_MAN_READ | GMAC_MAN_CLTTO;
sam_putreg(priv, SAM_GMAC_MAN, regval); sam_putreg(priv, SAM_GMAC_MAN, regval);
/* Wait until the PHY is again idle */ /* Wait until the PHY is again idle */
@ -2046,7 +2101,7 @@ static int sam_phyread(struct sam_gmac_s *priv, uint8_t phyaddr,
return ret; return ret;
} }
/* Return data */ /* Return the PHY data */
*phyval = (uint16_t)(sam_getreg(priv, SAM_GMAC_MAN) & GMAC_MAN_DATA_MASK); *phyval = (uint16_t)(sam_getreg(priv, SAM_GMAC_MAN) & GMAC_MAN_DATA_MASK);
return OK; return OK;
@ -2089,7 +2144,7 @@ static int sam_phywrite(struct sam_gmac_s *priv, uint8_t phyaddr,
/* Write the PHY Maintenance register */ /* Write the PHY Maintenance register */
regval = GMAC_MAN_DATA(phyval) | GMAC_MAN_WTN | GMAC_MAN_REGA(regaddr) | regval = GMAC_MAN_DATA(phyval) | GMAC_MAN_WTN | GMAC_MAN_REGA(regaddr) |
GMAC_MAN_PHYA(priv->phyaddr) | GMAC_MAN_WRITE; GMAC_MAN_PHYA(priv->phyaddr) | GMAC_MAN_WRITE | GMAC_MAN_CLTTO;
sam_putreg(priv, SAM_GMAC_MAN, regval); sam_putreg(priv, SAM_GMAC_MAN, regval);
/* Wait until the PHY is again IDLE */ /* Wait until the PHY is again IDLE */
@ -2132,13 +2187,11 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
/* Enable management port */ /* Enable management port */
regval = sam_getreg(priv, SAM_GMAC_NCR); sam_enablemdio(priv);
regval |= GMAC_NCR_MPE;
sam_putreg(priv, SAM_GMAC_NCR, regval);
/* Verify tht we can read the PHYID register */ /* Verify tht we can read the PHYID register */
ret = sam_phyread(priv, priv->phyaddr, MII_PHYID1, &phyid1); ret = sam_phyread(priv, priv->phyaddr, GMII_PHYID1, &phyid1);
if (ret < 0) if (ret < 0)
{ {
nlldbg("ERROR: Failed to read PHYID1\n"); nlldbg("ERROR: Failed to read PHYID1\n");
@ -2147,7 +2200,7 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
nllvdbg("PHYID1: %04x PHY address: %02x\n", phyid1, priv->phyaddr); nllvdbg("PHYID1: %04x PHY address: %02x\n", phyid1, priv->phyaddr);
ret = sam_phyread(priv, priv->phyaddr, MII_PHYID2, &phyid2); ret = sam_phyread(priv, priv->phyaddr, GMII_PHYID2, &phyid2);
if (ret < 0) if (ret < 0)
{ {
nlldbg("ERROR: Failed to read PHYID2\n"); nlldbg("ERROR: Failed to read PHYID2\n");
@ -2156,8 +2209,8 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
nllvdbg("PHYID2: %04x PHY address: %02x\n", phyid2, priv->phyaddr); nllvdbg("PHYID2: %04x PHY address: %02x\n", phyid2, priv->phyaddr);
if (phyid1 == MII_OUI_MSB && if (phyid1 == GMII_OUI_MSB &&
((phyid2 & MII_PHYID2_OUI) >> 10) == MII_OUI_LSB) ((phyid2 & GMII_PHYID2_OUI) >> 10) == GMII_OUI_LSB)
{ {
nllvdbg(" Vendor Model Number: %04x\n", ((phyid2 >> 4) & 0x3f)); nllvdbg(" Vendor Model Number: %04x\n", ((phyid2 >> 4) & 0x3f));
nllvdbg(" Model Revision Number: %04x\n", (phyid2 & 7)); nllvdbg(" Model Revision Number: %04x\n", (phyid2 & 7));
@ -2169,18 +2222,18 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
/* Setup control register */ /* Setup control register */
ret = sam_phyread(priv, priv->phyaddr, MII_MCR, &mcr); ret = sam_phyread(priv, priv->phyaddr, GMII_MCR, &mcr);
if (ret < 0) if (ret < 0)
{ {
nlldbg("ERROR: Failed to read MCR\n"); nlldbg("ERROR: Failed to read MCR\n");
goto errout; goto errout;
} }
mcr &= ~MII_MCR_ANENABLE; /* Remove autonegotiation enable */ mcr &= ~GMII_MCR_ANENABLE; /* Remove autonegotiation enable */
mcr &= ~(MII_MCR_LOOPBACK | MII_MCR_PDOWN); mcr &= ~(GMII_MCR_LOOPBACK | GMII_MCR_PDOWN);
mcr |= MII_MCR_ISOLATE; /* Electrically isolate PHY */ mcr |= GMII_MCR_ISOLATE; /* Electrically isolate PHY */
ret = sam_phywrite(priv, priv->phyaddr, MII_MCR, mcr); ret = sam_phywrite(priv, priv->phyaddr, GMII_MCR, mcr);
if (ret < 0) if (ret < 0)
{ {
nlldbg("ERROR: Failed to write MCR\n"); nlldbg("ERROR: Failed to write MCR\n");
@ -2191,11 +2244,11 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
* Next page 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 * Next page 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3
*/ */
advertise = MII_ADVERTISE_100BASETXFULL | MII_ADVERTISE_100BASETXHALF | advertise = GMII_ADVERTISE_100BASETXFULL | GMII_ADVERTISE_100BASETXHALF |
MII_ADVERTISE_10BASETXFULL | MII_ADVERTISE_10BASETXHALF | GMII_ADVERTISE_10BASETXFULL | GMII_ADVERTISE_10BASETXHALF |
MII_ADVERTISE_8023; GMII_ADVERTISE_8023;
ret = sam_phywrite(priv, priv->phyaddr, MII_ADVERTISE, advertise); ret = sam_phywrite(priv, priv->phyaddr, GMII_ADVERTISE, advertise);
if (ret < 0) if (ret < 0)
{ {
nlldbg("ERROR: Failed to write ANAR\n"); nlldbg("ERROR: Failed to write ANAR\n");
@ -2204,15 +2257,15 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
/* Read and modify control register */ /* Read and modify control register */
ret = sam_phyread(priv, priv->phyaddr, MII_MCR, &mcr); ret = sam_phyread(priv, priv->phyaddr, GMII_MCR, &mcr);
if (ret < 0) if (ret < 0)
{ {
nlldbg("ERROR: Failed to read MCR\n"); nlldbg("ERROR: Failed to read MCR\n");
goto errout; goto errout;
} }
mcr |= (MII_MCR_SPEED100 | MII_MCR_ANENABLE | MII_MCR_FULLDPLX); mcr |= (GMII_MCR_SPEED100 | GMII_MCR_ANENABLE | GMII_MCR_FULLDPLX);
ret = sam_phywrite(priv, priv->phyaddr, MII_MCR, mcr); ret = sam_phywrite(priv, priv->phyaddr, GMII_MCR, mcr);
if (ret < 0) if (ret < 0)
{ {
nlldbg("ERROR: Failed to write MCR\n"); nlldbg("ERROR: Failed to write MCR\n");
@ -2221,10 +2274,10 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
/* Restart Auto_negotiation */ /* Restart Auto_negotiation */
mcr |= MII_MCR_ANRESTART; mcr |= GMII_MCR_ANRESTART;
mcr &= ~MII_MCR_ISOLATE; mcr &= ~GMII_MCR_ISOLATE;
ret = sam_phywrite(priv, priv->phyaddr, MII_MCR, mcr); ret = sam_phywrite(priv, priv->phyaddr, GMII_MCR, mcr);
if (ret < 0) if (ret < 0)
{ {
nlldbg("ERROR: Failed to write MCR\n"); nlldbg("ERROR: Failed to write MCR\n");
@ -2238,7 +2291,7 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
timeout = 0; timeout = 0;
for (;;) for (;;)
{ {
ret = sam_phyread(priv, priv->phyaddr, MII_MSR, &msr); ret = sam_phyread(priv, priv->phyaddr, GMII_MSR, &msr);
if (ret < 0) if (ret < 0)
{ {
nlldbg("ERROR: Failed to read MSR\n"); nlldbg("ERROR: Failed to read MSR\n");
@ -2247,7 +2300,7 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
/* Completed successfully? */ /* Completed successfully? */
if ((msr & MII_MSR_ANEGCOMPLETE) != 0) if ((msr & GMII_MSR_ANEGCOMPLETE) != 0)
{ {
/* Yes.. break out of the loop */ /* Yes.. break out of the loop */
@ -2268,7 +2321,7 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
/* Get the AutoNeg Link partner base page */ /* Get the AutoNeg Link partner base page */
ret = sam_phyread(priv, priv->phyaddr, MII_LPA, &lpa); ret = sam_phyread(priv, priv->phyaddr, GMII_LPA, &lpa);
if (ret < 0) if (ret < 0)
{ {
nlldbg("ERROR: Failed to read ANLPAR\n"); nlldbg("ERROR: Failed to read ANLPAR\n");
@ -2280,26 +2333,26 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
regval = sam_getreg(priv, SAM_GMAC_NCFGR); regval = sam_getreg(priv, SAM_GMAC_NCFGR);
regval &= (GMAC_NCFGR_SPD | GMAC_NCFGR_FD); regval &= (GMAC_NCFGR_SPD | GMAC_NCFGR_FD);
if (((advertise & lpa) & MII_ADVERTISE_100BASETXFULL) != 0) if (((advertise & lpa) & GMII_ADVERTISE_100BASETXFULL) != 0)
{ {
/* Set MII for 100BaseTX and Full Duplex */ /* Set MII for 100BaseTX and Full Duplex */
regval |= (GMAC_NCFGR_SPD | GMAC_NCFGR_FD); regval |= (GMAC_NCFGR_SPD | GMAC_NCFGR_FD);
} }
else if (((advertise & lpa) & MII_ADVERTISE_10BASETXFULL) != 0) else if (((advertise & lpa) & GMII_ADVERTISE_10BASETXFULL) != 0)
{ {
/* Set MII for 10BaseT and Full Duplex */ /* Set MII for 10BaseT and Full Duplex */
regval |= GMAC_NCFGR_FD; regval |= GMAC_NCFGR_FD;
} }
else if (((advertise & lpa) & MII_ADVERTISE_100BASETXHALF) != 0) else if (((advertise & lpa) & GMII_ADVERTISE_100BASETXHALF) != 0)
{ {
/* Set MII for 100BaseTX and half Duplex */ /* Set MII for 100BaseTX and half Duplex */
regval |= GMAC_NCFGR_SPD; regval |= GMAC_NCFGR_SPD;
} }
#if 0 #if 0
else if (((advertise & lpa) & MII_ADVERTISE_10BASETXHALF) != 0) else if (((advertise & lpa) & GMII_ADVERTISE_10BASETXHALF) != 0)
{ {
/* set MII for 10BaseT and half Duplex */ /* set MII for 10BaseT and half Duplex */
} }
@ -2318,11 +2371,9 @@ static int sam_autonegotiate(struct sam_gmac_s *priv)
sam_putreg(priv, SAM_GMAC_UR, regval); sam_putreg(priv, SAM_GMAC_UR, regval);
errout: errout:
/* Disable management port */ /* Disable the management port */
regval = sam_getreg(priv, SAM_GMAC_NCR); sam_disablemdio(priv);
regval &= ~GMAC_NCR_MPE;
sam_putreg(priv, SAM_GMAC_NCR, regval);
return ret; return ret;
} }
@ -2350,18 +2401,18 @@ static bool sam_linkup(struct sam_gmac_s *priv)
/* Enable management port */ /* Enable management port */
regval = sam_getreg(priv, SAM_GMAC_NCR); sam_enablemdio(priv);
regval |= GMAC_NCR_MPE;
sam_putreg(priv, SAM_GMAC_NCR, regval);
ret = sam_phyread(priv, priv->phyaddr, MII_MSR, &msr); /* Read the PHY MSR register */
ret = sam_phyread(priv, priv->phyaddr, GMII_MSR, &msr);
if (ret < 0) if (ret < 0)
{ {
nlldbg("ERROR: Failed to read MSR: %d\n", ret); nlldbg("ERROR: Failed to read MSR: %d\n", ret);
goto errout; goto errout;
} }
if ((msr & MII_MSR_LINKSTATUS) == 0) if ((msr & GMII_MSR_LINKSTATUS) == 0)
{ {
nlldbg("ERROR: MSR LinkStatus: %04x\n", msr); nlldbg("ERROR: MSR LinkStatus: %04x\n", msr);
goto errout; goto errout;
@ -2379,20 +2430,20 @@ static bool sam_linkup(struct sam_gmac_s *priv)
regval = sam_getreg(priv, SAM_GMAC_NCFGR); regval = sam_getreg(priv, SAM_GMAC_NCFGR);
regval &= ~(GMAC_NCFGR_SPD | GMAC_NCFGR_FD); regval &= ~(GMAC_NCFGR_SPD | GMAC_NCFGR_FD);
if ((msr & MII_MSR_100BASETXFULL) != 0 && PHYSR_IS100FDX(physr)) if ((msr & GMII_MSR_100BASETXFULL) != 0 && PHYSR_IS100FDX(physr))
{ {
/* Set GMAC for 100BaseTX and Full Duplex */ /* Set GMAC for 100BaseTX and Full Duplex */
regval |= (GMAC_NCFGR_SPD | GMAC_NCFGR_FD); regval |= (GMAC_NCFGR_SPD | GMAC_NCFGR_FD);
} }
else if ((msr & MII_MSR_10BASETXFULL) != 0 && PHYSR_IS10FDX(physr)) else if ((msr & GMII_MSR_10BASETXFULL) != 0 && PHYSR_IS10FDX(physr))
{ {
/* Set MII for 10BaseT and Full Duplex */ /* Set MII for 10BaseT and Full Duplex */
regval |= GMAC_NCFGR_FD; regval |= GMAC_NCFGR_FD;
} }
else if ((msr & MII_MSR_100BASETXHALF) != 0 && PHYSR_IS100HDX(physr)) else if ((msr & GMII_MSR_100BASETXHALF) != 0 && PHYSR_IS100HDX(physr))
{ {
/* Set MII for 100BaseTX and Half Duplex */ /* Set MII for 100BaseTX and Half Duplex */
@ -2400,7 +2451,7 @@ static bool sam_linkup(struct sam_gmac_s *priv)
} }
#if 0 #if 0
else if ((msr & MII_MSR_10BASETXHALF) != 0 && PHYSR_IS10HDX(physr)) else if ((msr & GMII_MSR_10BASETXHALF) != 0 && PHYSR_IS10HDX(physr))
{ {
/* Set MII for 10BaseT and Half Duplex */ /* Set MII for 10BaseT and Half Duplex */
} }
@ -2416,13 +2467,66 @@ static bool sam_linkup(struct sam_gmac_s *priv)
errout: errout:
/* Disable management port */ /* Disable management port */
regval = sam_getreg(priv, SAM_GMAC_NCR); sam_disablemdio(priv);
regval &= ~GMAC_NCR_MPE;
sam_putreg(priv, SAM_GMAC_NCR, regval);
return linkup; return linkup;
} }
/****************************************************************************
* Function: sam_mdcclock
*
* Description:
* Configure the MDC clocking
*
* Parameters:
* priv - A reference to the private driver state structure
*
* Returned Value:
* None
*
****************************************************************************/
static void sam_mdcclock(struct sam_gmac_s *priv)
{
uint32_t ncfgr;
uint32_t ncr;
uint32_t enables;
/* Disable RX and TX momentarily */
ncr = sam_getreg(priv, SAM_GMAC_NCR);
enables = ncr & (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
ncr &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
sam_putreg(priv, SAM_GMAC_NCR, ncr);
/* Modify the NCFGR register based on the configured board MCK frequency */
ncfgr = sam_getreg(priv, SAM_GMAC_NCFGR);
ncfgr &= ~GMAC_NCFGR_CLK_MASK;
#if BOARD_MCK_FREQUENCY <= 20000000
ncfgr = GMAC_NCFGR_CLK_DIV8; /* MCK divided by 8 (MCK up to 20 MHz) */
#elif BOARD_MCK_FREQUENCY <= 40000000
ncfgr = GMAC_NCFGR_CLK_DIV16; /* MCK divided by 16 (MCK up to 40 MHz) */
#elif BOARD_MCK_FREQUENCY <= 80000000
ncfgr = GMAC_NCFGR_CLK_DIV32; /* MCK divided by 32 (MCK up to 80 MHz) */
#elif BOARD_MCK_FREQUENCY <= 120000000
ncfgr = GMAC_NCFGR_CLK_DIV48; /* MCK divided by 48 (MCK up to 120 MHz) */
#elif BOARD_MCK_FREQUENCY <= 160000000
ncfgr = GMAC_NCFGR_CLK_DIV64; /* MCK divided by 64 (MCK up to 160 MHz) */
#elif BOARD_MCK_FREQUENCY <= 240000000
ncfgr = GMAC_NCFGR_CLK_DIV96; /* MCK divided by 64 (MCK up to 240 MHz) */
#else
# error Invalid BOARD_MCK_FREQUENCY
#endif
sam_putreg(priv, SAM_GMAC_NCFGR, ncfgr);
/* Restore RX and TX enable settings */
ncr |= enables;
sam_putreg(priv, SAM_GMAC_NCR, ncr);
}
/**************************************************************************** /****************************************************************************
* Function: sam_phyinit * Function: sam_phyinit
* *
@ -2439,27 +2543,11 @@ errout:
static int sam_phyinit(struct sam_gmac_s *priv) static int sam_phyinit(struct sam_gmac_s *priv)
{ {
uint32_t regval;
int ret; int ret;
/* Configure PHY clocking */ /* Configure PHY clocking */
regval = sam_getreg(priv, SAM_GMAC_NCFGR); sam_mdcclock(priv);
regval &= ~GMAC_NCFGR_CLK_MASK;
#if BOARD_MCK_FREQUENCY > (160*1000*1000)
# error Supported MCK frequency
#elif BOARD_MCK_FREQUENCY > (80*1000*1000)
regval |= GMAC_NCFGR_CLK_DIV64; /* MCK divided by 64 (MCK up to 160 MHz) */
#elif BOARD_MCK_FREQUENCY > (40*1000*1000)
regval |= GMAC_NCFGR_CLK_DIV32; /* MCK divided by 32 (MCK up to 80 MHz) */
#elif BOARD_MCK_FREQUENCY > (20*1000*1000)
regval |= GMAC_NCFGR_CLK_DIV16; /* MCK divided by 16 (MCK up to 40 MHz) */
#else
regval |= GMAC_NCFGR_CLK_DIV8; /* MCK divided by 8 (MCK up to 20 MHz) */
#endif
sam_putreg(priv, SAM_GMAC_NCFGR, regval);
/* Check the PHY Address */ /* Check the PHY Address */
@ -2497,41 +2585,27 @@ static int sam_phyinit(struct sam_gmac_s *priv)
static inline void sam_ethgpioconfig(struct sam_gmac_s *priv) static inline void sam_ethgpioconfig(struct sam_gmac_s *priv)
{ {
/* Configure PIO pins to support GMAC */ /* Configure PIO pins to support GMAC in RGMII mode */
/* Configure GMAC PIO pins common to both MII and RMII */
#warning REVISIT: Do we need all of these?
sam_configpio(PIO_GMAC_TX0); sam_configpio(PIO_GMAC_TX0);
sam_configpio(PIO_GMAC_TX1); sam_configpio(PIO_GMAC_TX1);
#if 0
sam_configpio(PIO_GMAC_TX2); sam_configpio(PIO_GMAC_TX2);
sam_configpio(PIO_GMAC_TX3); sam_configpio(PIO_GMAC_TX3);
sam_configpio(PIO_GMAC_TX4);
sam_configpio(PIO_GMAC_TX5);
sam_configpio(PIO_GMAC_TX6);
sam_configpio(PIO_GMAC_TX7);
#endif
sam_configpio(PIO_GMAC_RX0); sam_configpio(PIO_GMAC_RX0);
sam_configpio(PIO_GMAC_RX1); sam_configpio(PIO_GMAC_RX1);
#if 0
sam_configpio(PIO_GMAC_RX2); sam_configpio(PIO_GMAC_RX2);
sam_configpio(PIO_GMAC_RX3); sam_configpio(PIO_GMAC_RX3);
sam_configpio(PIO_GMAC_RX4);
sam_configpio(PIO_GMAC_RX5);
sam_configpio(PIO_GMAC_RX6);
sam_configpio(PIO_GMAC_RX7);
#endif
sam_configpio(PIO_GMAC_TXEN);
sam_configpio(PIO_GMAC_TXER);
sam_configpio(PIO_GMAC_TXCK); sam_configpio(PIO_GMAC_TXCK);
sam_configpio(PIO_GMAC_TXEN);
sam_configpio(PIO_GMAC_RXCK); sam_configpio(PIO_GMAC_RXCK);
sam_configpio(PIO_GMAC_RXDV); sam_configpio(PIO_GMAC_RXDV);
sam_configpio(PIO_GMAC_RXER); sam_configpio(PIO_GMAC_RXER);
sam_configpio(PIO_GMAC_125CK);
sam_configpio(PIO_GMAC_125CKO);
sam_configpio(PIO_GMAC_COL);
sam_configpio(PIO_GMAC_CRS);
sam_configpio(PIO_GMAC_MDC); sam_configpio(PIO_GMAC_MDC);
sam_configpio(PIO_GMAC_MDIO); sam_configpio(PIO_GMAC_MDIO);
sam_configpio(PIO_GMAC_125CK);
} }
/**************************************************************************** /****************************************************************************