Complete replacement of PHY logic for Am79c874

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1573 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2009-03-07 23:29:17 +00:00
parent dc036906b7
commit c4627f5cdc

View File

@ -123,12 +123,28 @@
# error "Unsupported CONFIG_EZ80_PKTBUFSIZE value"
#endif
/* Am79c874 PHY configuration */
#define EZ80_EMAC_AUTONEG 0
#define EZ80_EMAC_100BFD 1
#define EZ80_EMAC_100BHD 2
#define EZ80_EMAC_10BFD 3
#define EZ80_EMAC_10BHD 4
#ifndef CONFIG_EZ80_PHYCONFIG
# define CONFIG_EZ80_PHYCONFIG EZ80_EMAC_10BFD
#endif
/* Select the fastest MDC clock that does not exceed 25MHz. The MDC
* clock derives from the SCLK divided by 4, 6, 8, 10, 14, 20, or 28.
*/
#ifndef CONFIG_EZ80_MDCDIV
# define CONFIG_EZ80_MDCDIV EMAC_MDC_DIV4
# ifdef CONFIG_EZ80_PHYAM79C874
# define CONFIG_EZ80_MDCDIV EMAC_MDC_DIV20
# else
# define CONFIG_EZ80_MDCDIV EMAC_MDC_DIV4
# endif
#endif
/* Select the Tx poll timer. If not specified, a 10MS timer is set */
@ -319,7 +335,7 @@ static void ez80emac_miiwrite(FAR struct ez80emac_driver_s *priv, ubyte offse
static uint16 ez80emac_miiread(FAR struct ez80emac_driver_s *priv, uint32 offset);
static boolean ez80emac_miipoll(FAR struct ez80emac_driver_s *priv, uint32 offset,
uint16 bits, boolean bclear);
static void ez80emac_miiautonegotiate(FAR struct ez80emac_driver_s *priv);
static int ez80emac_miiautonegotiate(FAR struct ez80emac_driver_s *priv);
/* Multi-cast filtering */
@ -523,7 +539,156 @@ static boolean ez80emac_miipoll(FAR struct ez80emac_driver_s *priv, uint32 offse
*
****************************************************************************/
static void ez80emac_miiautonegotiate(FAR struct ez80emac_driver_s *priv)
#ifdef CONFIG_EZ80_PHYAM79C874
static int ez80emac_miiautonegotiate(FAR struct ez80emac_driver_s *priv)
{
uint16 phyval;
boolean bauto;
int ret = OK;
int i;
/* Verify that the detect PHY is an AMD Am87c874 as expected */
#ifdef CONFIG_DEBUG /* Parameter checking only done when DEBUG is enabled */
phyval = ez80emac_miiread(priv, MII_PHYID1);
if (phyval != MII_PHYID1_AM79C874)
{
ndbg("Not an Am79c874 PHY: PHY1=%04x vs %04x\n", phyval, MII_PHYID1_AM79C874);
ret = -ENODEV;
goto dumpregs;
}
phyval = ez80emac_miiread(priv, MII_PHYID2);
if (phyval != MII_PHYID2_AM79C874)
{
ndbg("Not an Am79c874 PHY: PHY2=%04x vs %04x\n", phyval, MII_PHYID2_AM79C874);
ret = -ENODEV;
goto dumpregs;
}
#endif
/* Check if the PHY can do auto-negotiation */
phyval = ez80emac_miiread(priv, MII_MSR);
if (phyval & MII_MSR_ANEGABLE)
{
phyval = MII_MCR_ANRESTART | MII_MCR_ANENABLE;
bauto = TRUE;
}
else
{
phyval = 0;
bauto = FALSE;
/* PADEN - EMAC pads all short frames by adding zeroes to the end of
* the data field. This bit is used in conjunction with ADPADN
* and VLPAD.
* CRCEN - Append CRC to every frame regardless of padding options.
*/
outp(EZ80_EMAC_CFG1, EMAC_CFG1_PADEN|EMAC_CFG1_CRCEN);
}
/* Set the configured link capabilities */
#if CONFIG_EZ80_PHYCONFIG == EZ80_EMAC_AUTONEG
ndbg("Configure autonegotiation\n");
if (bauto)
{
ez80emac_miiwrite(priv, MII_ADVERTISE,
MII_ADVERTISE_100BASETXFULL|MII_ADVERTISE_100BASETXHALF|
MII_ADVERTISE_10BASETXFULL|MII_ADVERTISE_10BASETXHALF|
MII_ADVERTISE_CSMA);
}
else
{
ndbg("Am79c784 is not capable of autonegotiation\n");
}
#elif CONFIG_EZ80_PHYCONFIG == EZ80_EMAC_100BFD
ndbg("100BASETX full duplex\n");
phyval |= MII_MCR_SPEED100 | MII_MCR_FULLDPLX;
ez80emac_miiwrite(priv, MII_ADVERTISE,
MII_ADVERTISE_100BASETXFULL|MII_ADVERTISE_100BASETXHALF|
MII_ADVERTISE_10BASETXFULL|MII_ADVERTISE_10BASETXHALF|
MII_ADVERTISE_CSMA);
#elif CONFIG_EZ80_PHYCONFIG == EZ80_EMAC_100BHD
ndbg("100BASETX half duplex\n");
phyval |= MII_MCR_SPEED100;
ez80emac_miiwrite(priv, MII_ADVERTISE,
MII_ADVERTISE_100BASETXHALF|MII_ADVERTISE_10BASETXFULL|
MII_ADVERTISE_10BASETXHALF|MII_ADVERTISE_CSMA);
#elif CONFIG_EZ80_PHYCONFIG == EZ80_EMAC_10BFD
ndbg("10BASETX full duplex\n");
phyval |= MII_MCR_FULLDPLX;
ez80emac_miiwrite(priv, MII_ADVERTISE,
MII_ADVERTISE_10BASETXFULL|MII_ADVERTISE_10BASETXHALF|MII_ADVERTISE_CSMA);
#elif CONFIG_EZ80_PHYCONFIG == EZ80_EMAC_10BHD
ndbg("10BASETX half duplex\n");
ez80emac_miiwrite(priv, MII_ADVERTISE,
MII_ADVERTISE_10BASETXHALF|MII_ADVERTISE_CSMA);
#else
# error "No recognized value of CONFIG_EZ80_PHYCONFIG"
#endif
ez80emac_miiwrite(priv, MII_MCR, phyval);
/* Wait for a link to be established */
for (i = 0; i < 50; i++)
{
phyval = ez80emac_miiread(priv, MII_MSR);
if ((phyval & (MII_MSR_ANEGCOMPLETE | MII_MSR_LINKSTATUS)) != 0)
{
break;
}
up_mdelay(10);
}
if ((phyval & MII_MSR_LINKSTATUS) == 0)
{
ndbg("Failed to establish link\n");
ret = -ETIMEDOUT;
}
else
{
/* Read the Am79c874 diagnostics register for link settings */
phyval = ez80emac_miiread(priv, MII_AM79C874_DIAGNOSTIC);
if (phyval & AM79C874_DIAG_FULLDPLX)
{
outp(EZ80_EMAC_CFG1, EMAC_CFG1_PADEN|EMAC_CFG1_CRCEN|EMAC_CFG1_FULLHD);
}
else
{
outp(EZ80_EMAC_CFG1, EMAC_CFG1_PADEN|EMAC_CFG1_CRCEN);
}
}
dumpregs:
nvdbg("Am79c874 MII registers (FIAD=%lx)\n", CONFIG_EZ80_FIAD);
nvdbg(" MII_MCR: %04x\n", ez80emac_miiread(priv, MII_MCR));
nvdbg(" MII_MSR: %04x\n", ez80emac_miiread(priv, MII_MSR));
nvdbg(" MII_PHYID1: %04x\n", ez80emac_miiread(priv, MII_PHYID1));
nvdbg(" MII_PHYID2: %04x\n", ez80emac_miiread(priv, MII_PHYID2));
nvdbg(" MII_ADVERTISE: %04x\n", ez80emac_miiread(priv, MII_ADVERTISE));
nvdbg(" MII_LPA: %04x\n", ez80emac_miiread(priv, MII_LPA));
nvdbg(" MII_EXPANSION: %04x\n", ez80emac_miiread(priv, MII_EXPANSION));
nvdbg(" MII_DIAGNOSTICS: %04x\n", ez80emac_miiread(priv, MII_AM79C874_DIAGNOSTIC));
nvdbg("EMAC CFG1: %02x\n", inp(EZ80_EMAC_CFG1));
return ret;
}
#else
static int ez80emac_miiautonegotiate(FAR struct ez80emac_driver_s *priv)
{
uint16 advertise;
uint16 lpa;
@ -656,7 +821,10 @@ static void ez80emac_miiautonegotiate(FAR struct ez80emac_driver_s *priv)
nvdbg(" MII_ADVERTISE: %04x\n", ez80emac_miiread(priv, MII_ADVERTISE));
nvdbg(" MII_LPA: %04x\n", ez80emac_miiread(priv, MII_LPA));
nvdbg(" MII_EXPANSION: %04x\n", ez80emac_miiread(priv, MII_EXPANSION));
nvdbg("EMAC CFG1: %02x\n", inp(EZ80_EMAC_CFG11));
return OK;
}
#endif
/****************************************************************************
* Function: ez80emac_machash
@ -1308,9 +1476,13 @@ static int ez80emac_ifup(FAR struct uip_driver_s *dev)
ubyte regval;
int ret;
ndbg("Bringing up: %d.%d.%d.%d\n",
dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff,
(dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24)
ndbg("Bringing up: MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
dev->d_mac.ether_addr_octet[0], dev->d_mac.ether_addr_octet[1],
dev->d_mac.ether_addr_octet[2], dev->d_mac.ether_addr_octet[3],
dev->d_mac.ether_addr_octet[4], dev->d_mac.ether_addr_octet[5]);
ndbg(" IP %d.%d.%d.%d\n",
dev->d_ipaddr >> 24, (dev->d_ipaddr >> 16) & 0xff,
(dev->d_ipaddr >> 8) & 0xff, dev->d_ipaddr & 0xff);
/* Bring up the interface -- Must be down right now */
@ -1678,7 +1850,7 @@ static int ez80_emacinitialize(void)
/* Set auto-negotion */
ez80emac_miiautonegotiate(priv);
ret = ez80emac_miiautonegotiate(priv);
/* Initialize DMA / FIFO */