SAMA5 GMAC and GMII support is code complete and ready for test

This commit is contained in:
Gregory Nutt 2013-09-27 13:12:04 -06:00
parent e1f9d22482
commit f7e4f25760
8 changed files with 381 additions and 392 deletions

7
TODO
View File

@ -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

View File

@ -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
If SAMA5_GMAC_AUTONEG is not defined, then this may be defined to
select full duplex mode. Default: half-duplex
choice
prompt "GMAC Speed"
default SAMA5_GMAC_ETH100MBPS
---help---
If autonegation is not used, then you must select the fixed speed
of the PHY
config SAMA5_GMAC_ETH10MBPS
bool "10 Mbps"
---help---
If SAMA5_GMAC_AUTONEG is not defined, then this may be defined to select 10 MBps
speed. Default: 100 Mbps
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
speed. Default: 100 Mbps
config SAMA5_GMAC_PHYSR
int "PHY Status Register Address (decimal)"
depends on SAMA5_GMAC_AUTONEG
config SAMA5_GMAC_ETH1000MBPS
bool "1000 Mbps"
---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.
If SAMA5_GMAC_AUTONEG is not defined, then this may be defined to select 1000 MBps
speed. Default: 100 Mbps
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.
config SAMA5_GMAC_PHYSR_ALTMODE
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 speed and full/half duplex mode bits.
config SAMA5_GMAC_PHYSR_10HD
hex "10MBase-T Half 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 10Mbps, half duplex setting.
config SAMA5_GMAC_PHYSR_100HD
hex "100Base-T Half 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, half duplex setting.
config SAMA5_GMAC_PHYSR_10FD
hex "10Base-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 10Mbps, full duplex setting.
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"

View File

@ -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 */

View File

@ -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 */

View File

@ -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);

View File

@ -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_phywrite(priv, priv->phyaddr, GMII_MCR, mcr);
ret = sam_phyread(priv, priv->phyaddr, GMII_MCR, &phyval);
if (ret < 0)
{
nlldbg("ERROR: Failed to write MCR\n");
nlldbg("ERROR: Failed to read MCR register: %d\n", ret);
goto errout;
}
nllvdbg(" MCR: %04x\n", mcr);
phyval |= GMII_MCR_ANRESTART;
/* Check AutoNegotiate complete */
ret = sam_phywrite(priv, priv->phyaddr, GMII_MCR, phyval);
if (ret < 0)
{
nlldbg("ERROR: Failed to write MCR register: %d\n", ret);
goto errout;
}
nllvdbg(" MCR: 0x%X\n", phyval);
/* 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 */
if ((btsr & GMII_1000BTSR_LP1000BASETFULL) != 0 &&
(btcr & GMII_1000BTCR_1000BASETHALF) != 0)
{
/* Set RGMII for 1000BaseTX 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 */
linkmode = GMAC_NCFGR_GBE;
break;
}
/* Get the Autonegotiation Link partner base page */
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;
}
}
/* Setup the GMAC link speed */
/* 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);
if (((advertise & lpa) & GMII_ADVERTISE_100BASETXFULL) != 0)
{
/* Set MII for 100BaseTX and Full Duplex */
regval |= (GMAC_NCFGR_SPD | GMAC_NCFGR_FD);
}
else if (((advertise & lpa) & GMII_ADVERTISE_10BASETXFULL) != 0)
{
/* Set MII for 10BaseT and Full Duplex */
regval |= GMAC_NCFGR_FD;
}
else if (((advertise & lpa) & GMII_ADVERTISE_100BASETXHALF) != 0)
{
/* Set MII for 100BaseTX and half Duplex */
regval |= GMAC_NCFGR_SPD;
}
#if 0
else if (((advertise & lpa) & GMII_ADVERTISE_10BASETXHALF) != 0)
{
/* set MII for 10BaseT and half Duplex */
}
#endif
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;
uint32_t ncr;
/* Enable management port */
/* Disable RX and TX momentarily */
sam_enablemdio(priv);
ncr = sam_getreg(priv, SAM_GMAC_NCR);
sam_putreg(priv, SAM_GMAC_NCR, ncr & ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN));
/* 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;
}
if ((msr & GMII_MSR_LINKSTATUS) == 0)
{
nlldbg("ERROR: MSR LinkStatus: %04x\n", msr);
goto errout;
}
/* Re-configure Link speed */
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);
regval &= ~(GMAC_NCFGR_SPD | GMAC_NCFGR_FD | GMAC_NCFGR_GBE);
if ((msr & GMII_MSR_100BASETXFULL) != 0 && PHYSR_IS100FDX(physr))
{
/* Set GMAC for 100BaseTX and Full Duplex */
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);
#if defined(SAMA5_GMAC_ETH100MBPS)
regval |= GMAC_NCFGR_SPD;
#elif defined(SAMA5_GMAC_ETH1000MBPS) */
regval |= GMAC_NCFGR_GBE;
#endif
/* Start the GMAC transfers */
nllvdbg("Link is up\n");
linkup = true;
errout:
/* Disable management port */
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;
}

View File

@ -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 */
/* 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 */
#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 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) */
/*********************************************************************************************

View File

@ -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 */