arch/arm/src/lpc17xx_40xx/lpc17_40_ethernet.c: Fix the initialization for DP83848x PHYs. The DP83848x requires the RMII mode to be manually enabled through the MII_DP83848C_RBR register. Before querying the speed and mode it should wait for the link to be established.
This commit is contained in:
parent
41d3ef5f1b
commit
a1f1adb878
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/lpc17xx_40xx/lpc17_40_ethernet.c
|
||||
*
|
||||
* Copyright (C) 2010-2015, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2010-2015, 2017-2019 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -80,7 +80,9 @@
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
/* If processing is not done at the interrupt level, then work queue support
|
||||
* is required.
|
||||
*/
|
||||
@ -130,6 +132,7 @@
|
||||
#define PKTBUF_SIZE (MAX_NETDEV_PKTSIZE + CONFIG_NET_GUARDSIZE)
|
||||
|
||||
/* Debug Configuration *****************************************************/
|
||||
|
||||
/* Register debug -- can only happen of CONFIG_DEBUG_NET_INFO is selected */
|
||||
|
||||
#ifndef CONFIG_DEBUG_NET_INFO
|
||||
@ -178,6 +181,7 @@
|
||||
#define GPIO_NENET_PINS 10
|
||||
|
||||
/* PHYs *********************************************************************/
|
||||
|
||||
/* Select PHY-specific values. Add more PHYs as needed. */
|
||||
|
||||
#if defined(CONFIG_ETH0_PHY_KS8721)
|
||||
@ -279,8 +283,8 @@
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* The lpc17_40_driver_s encapsulates all state information for a single hardware
|
||||
* interface
|
||||
/* The lpc17_40_driver_s encapsulates all state information for a single
|
||||
* hardware interface
|
||||
*/
|
||||
|
||||
struct lpc17_40_driver_s
|
||||
@ -330,13 +334,15 @@ static struct lpc17_40_driver_s g_ethdrvr[CONFIG_LPC17_40_NINTERFACES];
|
||||
* MDIO on P1[17] or P2[9]. The board.h file will define GPIO_ENET_MDC and
|
||||
* PGIO_ENET_MDIO to selec which pin setting to use.
|
||||
*
|
||||
* On older Rev '-' devices, P1[6] ENET-TX_CLK would also have be to configured.
|
||||
* On older Rev '-' devices, P1[6] ENET-TX_CLK would also have be to
|
||||
* configured.
|
||||
*/
|
||||
|
||||
static const uint16_t g_enetpins[GPIO_NENET_PINS] =
|
||||
{
|
||||
GPIO_ENET_TXD0, GPIO_ENET_TXD1, GPIO_ENET_TXEN, GPIO_ENET_CRS, GPIO_ENET_RXD0,
|
||||
GPIO_ENET_RXD1, GPIO_ENET_RXER, GPIO_ENET_REFCLK, GPIO_ENET_MDC, GPIO_ENET_MDIO
|
||||
GPIO_ENET_TXD0, GPIO_ENET_TXD1, GPIO_ENET_TXEN, GPIO_ENET_CRS,
|
||||
GPIO_ENET_RXD0, GPIO_ENET_RXD1, GPIO_ENET_RXER, GPIO_ENET_REFCLK,
|
||||
GPIO_ENET_MDC, GPIO_ENET_MDIO
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@ -476,8 +482,8 @@ static void lpc17_40_checkreg(uint32_t addr, uint32_t val, bool iswrite)
|
||||
static uint32_t count = 0;
|
||||
static bool prevwrite = false;
|
||||
|
||||
/* Is this the same value that we read from/wrote to the same register last time?
|
||||
* Are we polling the register? If so, suppress the output.
|
||||
/* Is this the same value that we read from/wrote to the same register
|
||||
* last time? Are we polling the register? If so, suppress the output.
|
||||
*/
|
||||
|
||||
if (addr == prevaddr && val == preval && prevwrite == iswrite)
|
||||
@ -693,8 +699,8 @@ static int lpc17_40_transmit(struct lpc17_40_driver_s *priv)
|
||||
|
||||
/* Setup the TX timeout watchdog (perhaps restarting the timer) */
|
||||
|
||||
(void)wd_start(priv->lp_txtimeout, LPC17_40_TXTIMEOUT, lpc17_40_txtimeout_expiry,
|
||||
1, (uint32_t)priv);
|
||||
(void)wd_start(priv->lp_txtimeout, LPC17_40_TXTIMEOUT,
|
||||
lpc17_40_txtimeout_expiry, 1, (uint32_t)priv);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -758,14 +764,14 @@ static int lpc17_40_txpoll(struct net_driver_s *dev)
|
||||
|
||||
if (!devif_loopback(&priv->lp_dev))
|
||||
{
|
||||
/* Send this packet. In this context, we know that there is space for
|
||||
* at least one more packet in the descriptor list.
|
||||
/* Send this packet. In this context, we know that there is space
|
||||
* for at least one more packet in the descriptor list.
|
||||
*/
|
||||
|
||||
lpc17_40_transmit(priv);
|
||||
|
||||
/* Check if there is room in the device to hold another packet. If not,
|
||||
* return any non-zero value to terminate the poll.
|
||||
/* Check if there is room in the device to hold another packet. If
|
||||
* not, return any non-zero value to terminate the poll.
|
||||
*/
|
||||
|
||||
ret = lpc17_40_txdesc(priv);
|
||||
@ -783,14 +789,14 @@ static int lpc17_40_txpoll(struct net_driver_s *dev)
|
||||
* Function: lpc17_40_response
|
||||
*
|
||||
* Description:
|
||||
* While processing an RxDone event, higher logic decides to send a packet,
|
||||
* possibly a response to the incoming packet (but probably not, in reality).
|
||||
* However, since the Rx and Tx operations are decoupled, there is no
|
||||
* guarantee that there will be a Tx descriptor available at that time.
|
||||
* This function will perform that check and, if no Tx descriptor is
|
||||
* available, this function will (1) stop incoming Rx processing (bad), and
|
||||
* (2) hold the outgoing packet in a pending state until the next Tx
|
||||
* interrupt occurs.
|
||||
* While processing an RxDone event, higher logic decides to send a
|
||||
* packet, possibly a response to the incoming packet (but probably not,
|
||||
* in reality). However, since the Rx and Tx operations are decoupled,
|
||||
* there is no guarantee that there will be a Tx descriptor available at
|
||||
* that time. This function will perform that check and, if no Tx
|
||||
* descriptor is available, this function will (1) stop incoming Rx
|
||||
* processing (bad), and (2) hold the outgoing packet in a pending state
|
||||
* until the next Tx interrupt occurs.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Reference to the driver state structure
|
||||
@ -905,20 +911,23 @@ static void lpc17_40_rxdone_work(FAR void *arg)
|
||||
|
||||
/* else */ if (pktlen > CONFIG_NET_ETH_PKTSIZE + CONFIG_NET_GUARDSIZE)
|
||||
{
|
||||
nwarn("WARNING: Too big. considx: %08x prodidx: %08x pktlen: %d rxstat: %08x\n",
|
||||
nwarn("WARNING: Too big. considx: %08x prodidx: %08x pktlen: %d "
|
||||
"rxstat: %08x\n",
|
||||
considx, prodidx, pktlen, *rxstat);
|
||||
NETDEV_RXERRORS(&priv->lp_dev);
|
||||
}
|
||||
else if ((*rxstat & RXSTAT_INFO_LASTFLAG) == 0)
|
||||
{
|
||||
ninfo("Fragment. considx: %08x prodidx: %08x pktlen: %d rxstat: %08x\n",
|
||||
ninfo("Fragment. considx: %08x prodidx: %08x pktlen: %d "
|
||||
"rxstat: %08x\n",
|
||||
considx, prodidx, pktlen, *rxstat);
|
||||
NETDEV_RXFRAGMENTS(&priv->lp_dev);
|
||||
fragment = true;
|
||||
}
|
||||
else if (fragment)
|
||||
{
|
||||
ninfo("Last fragment. considx: %08x prodidx: %08x pktlen: %d rxstat: %08x\n",
|
||||
ninfo("Last fragment. considx: %08x prodidx: %08x pktlen: %d "
|
||||
"rxstat: %08x\n",
|
||||
considx, prodidx, pktlen, *rxstat);
|
||||
NETDEV_RXFRAGMENTS(&priv->lp_dev);
|
||||
fragment = false;
|
||||
@ -1095,7 +1104,6 @@ static void lpc17_40_rxdone_work(FAR void *arg)
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Function: lpc17_40_txdone_work
|
||||
*
|
||||
@ -1187,6 +1195,7 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
|
||||
lpc17_40_putreg(status, LPC17_40_ETH_INTCLR);
|
||||
|
||||
/* Handle each pending interrupt **************************************/
|
||||
|
||||
/* Check for Wake-Up on Lan *******************************************/
|
||||
|
||||
#ifdef CONFIG_LPC17_40_ETH_WOL
|
||||
@ -1197,6 +1206,7 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
|
||||
else
|
||||
#endif
|
||||
/* Fatal Errors *******************************************************/
|
||||
|
||||
/* RX OVERRUN -- Fatal overrun error in the receive queue. The fatal
|
||||
* interrupt should be resolved by a Rx soft-reset. The bit is not
|
||||
* set when there is a nonfatal overrun error.
|
||||
@ -1228,12 +1238,14 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
|
||||
else
|
||||
{
|
||||
/* Check for receive events ***************************************/
|
||||
|
||||
/* RX ERROR -- Triggered on receive errors: AlignmentError,
|
||||
* RangeError, LengthError, SymbolError, CRCError or NoDescriptor
|
||||
* or Overrun. NOTE: (1) We will still need to call lpc17_40_rxdone_process
|
||||
* on RX errors to bump the considx over the bad packet. (2) The
|
||||
* DMA engine reports bogus length errors, making this a pretty
|
||||
* useless (as well as annoying) check anyway.
|
||||
* or Overrun. NOTE: (1) We will still need to call
|
||||
* lpc17_40_rxdone_process on RX errors to bump the considx over
|
||||
* the bad packet. (2) The DMA engine reports bogus length
|
||||
* errors, making this a pretty useless (as well as annoying)
|
||||
* check anyway.
|
||||
*/
|
||||
|
||||
if ((status & ETH_INT_RXERR) != 0)
|
||||
@ -1256,8 +1268,8 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
|
||||
|
||||
if ((status & ETH_INT_RXFIN) != 0 || (status & ETH_INT_RXDONE) != 0)
|
||||
{
|
||||
/* We have received at least one new incoming packet. */
|
||||
/* Disable further TX interrupts for now. TX interrupts will
|
||||
/* We have received at least one new incoming packet.
|
||||
* Disable further TX interrupts for now. TX interrupts will
|
||||
* be re-enabled after the work has been processed.
|
||||
*/
|
||||
|
||||
@ -1268,15 +1280,16 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
|
||||
* perhaps cancelling any pending RX work.
|
||||
*/
|
||||
|
||||
work_queue(ETHWORK, &priv->lp_rxwork, (worker_t)lpc17_40_rxdone_work,
|
||||
priv, 0);
|
||||
work_queue(ETHWORK, &priv->lp_rxwork,
|
||||
(worker_t)lpc17_40_rxdone_work, priv, 0);
|
||||
}
|
||||
|
||||
/* Check for Tx events ********************************************/
|
||||
|
||||
/* TX ERROR -- Triggered on transmit errors: LateCollision,
|
||||
* ExcessiveCollision and ExcessiveDefer, NoDescriptor or Underrun.
|
||||
* NOTE: We will still need to call lpc17_40_txdone_process() in order to
|
||||
* clean up after the failed transmit.
|
||||
* NOTE: We will still need to call lpc17_40_txdone_process() in
|
||||
* order to clean up after the failed transmit.
|
||||
*/
|
||||
|
||||
if ((status & ETH_INT_TXERR) != 0)
|
||||
@ -1305,8 +1318,9 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
|
||||
{
|
||||
NETDEV_TXDONE(&priv->lp_dev);
|
||||
|
||||
/* A packet transmission just completed */
|
||||
/* Cancel the pending Tx timeout */
|
||||
/* A packet transmission just completed.
|
||||
* Cancel the pending Tx timeout
|
||||
*/
|
||||
|
||||
wd_cancel(priv->lp_txtimeout);
|
||||
|
||||
@ -1328,8 +1342,8 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
|
||||
* perhaps cancelling any pending TX work.
|
||||
*/
|
||||
|
||||
work_queue(ETHWORK, &priv->lp_txwork, (worker_t)lpc17_40_txdone_work,
|
||||
priv, 0);
|
||||
work_queue(ETHWORK, &priv->lp_txwork,
|
||||
(worker_t)lpc17_40_txdone_work, priv, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1669,10 +1683,10 @@ static int lpc17_40_ifup(struct net_driver_s *dev)
|
||||
|
||||
/* Set up RX filter and configure to accept broadcast addresses, multicast
|
||||
* addresses, and perfect station address matches. We should also accept
|
||||
* perfect matches and, most likely, broadcast (for example, for ARP requests).
|
||||
* Other RX filter options will only be enabled if so selected. NOTE: There
|
||||
* is a selection CONFIG_NET_BROADCAST, but this enables receipt of UDP
|
||||
* broadcast packets inside of the stack.
|
||||
* perfect matches and, most likely, broadcast (for example, for ARP
|
||||
* requests). Other RX filter options will only be enabled if so
|
||||
* selected. NOTE: There is a selection CONFIG_NET_BROADCAST, but this
|
||||
* enables receipt of UDP broadcast packets inside of the stack.
|
||||
*/
|
||||
|
||||
regval = ETH_RXFLCTRL_PERFEN | ETH_RXFLCTRL_BCASTEN;
|
||||
@ -1852,7 +1866,8 @@ static void lpc17_40_txavail_work(FAR void *arg)
|
||||
|
||||
static int lpc17_40_txavail(struct net_driver_s *dev)
|
||||
{
|
||||
FAR struct lpc17_40_driver_s *priv = (FAR struct lpc17_40_driver_s *)dev->d_private;
|
||||
FAR struct lpc17_40_driver_s *priv =
|
||||
(FAR struct lpc17_40_driver_s *)dev->d_private;
|
||||
|
||||
/* Is our single poll work structure available? It may not be if there
|
||||
* are pending polling actions and we will have to ignore the Tx
|
||||
@ -1947,7 +1962,7 @@ static uint32_t lpc17_40_calcethcrc(const uint8_t *data, size_t length)
|
||||
|
||||
if (((crc >> 31) ^ (byte >> 0)) & 0x00000001)
|
||||
{
|
||||
q0 = 0x2608EDB8;
|
||||
q0 = 0x2608edb8;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2025,8 +2040,8 @@ static int lpc17_40_addmac(struct net_driver_s *dev, const uint8_t *mac)
|
||||
*
|
||||
* AcceptUnicastHashEn: When set to ’1’, unicast frames that pass the
|
||||
* imperfect hash filter are accepted.
|
||||
* AcceptMulticastHashEn When set to ’1’, multicast frames that pass the
|
||||
* imperfect hash filter are accepted.
|
||||
* AcceptMulticastHashEn When set to ’1’, multicast frames that pass
|
||||
* the imperfect hash filter are accepted.
|
||||
*/
|
||||
|
||||
regval = lpc17_40_getreg(LPC17_40_ETH_RXFLCTRL);
|
||||
@ -2042,8 +2057,8 @@ static int lpc17_40_addmac(struct net_driver_s *dev, const uint8_t *mac)
|
||||
* Function: lpc17_40_rmmac
|
||||
*
|
||||
* Description:
|
||||
* NuttX Callback: Remove the specified MAC address from the hardware multicast
|
||||
* address filtering
|
||||
* NuttX Callback: Remove the specified MAC address from the hardware
|
||||
* multicast address filtering
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Reference to the NuttX driver state structure
|
||||
@ -2105,10 +2120,10 @@ static int lpc17_40_rmmac(struct net_driver_s *dev, const uint8_t *mac)
|
||||
|
||||
if (regval == 0 && lpc17_40_getreg(regaddr2) == 0)
|
||||
{
|
||||
/* AcceptUnicastHashEn: When set to ’1’, unicast frames that pass the
|
||||
* imperfect hash filter are accepted.
|
||||
* AcceptMulticastHashEn When set to ’1’, multicast frames that pass the
|
||||
* imperfect hash filter are accepted.
|
||||
/* AcceptUnicastHashEn: When set to ’1’, unicast frames that pass
|
||||
* the imperfect hash filter are accepted.
|
||||
* AcceptMulticastHashEn When set to ’1’, multicast frames that
|
||||
* pass the imperfect hash filter are accepted.
|
||||
*/
|
||||
|
||||
regval = lpc17_40_getreg(LPC17_40_ETH_RXFLCTRL);
|
||||
@ -2156,9 +2171,11 @@ static int lpc17_40_eth_ioctl(struct net_driver_s *dev, int cmd,
|
||||
#ifdef CONFIG_ARCH_PHY_INTERRUPT
|
||||
case SIOCMIINOTIFY: /* Set up for PHY event notifications */
|
||||
{
|
||||
struct mii_iotcl_notify_s *req = (struct mii_iotcl_notify_s *)((uintptr_t)arg);
|
||||
struct mii_iotcl_notify_s *req =
|
||||
(struct mii_iotcl_notify_s *)((uintptr_t)arg);
|
||||
|
||||
ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo, req->arg);
|
||||
ret = phy_notify_subscribe(dev->d_ifname, req->pid, req->signo,
|
||||
req->arg);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Enable PHY link up/down interrupts */
|
||||
@ -2170,7 +2187,9 @@ static int lpc17_40_eth_ioctl(struct net_driver_s *dev, int cmd,
|
||||
#endif
|
||||
case SIOCGMIIPHY: /* Get MII PHY address */
|
||||
{
|
||||
struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg);
|
||||
struct mii_ioctl_data_s *req =
|
||||
(struct mii_ioctl_data_s *)((uintptr_t)arg);
|
||||
|
||||
req->phy_id = priv->lp_phyaddr;
|
||||
ret = OK;
|
||||
}
|
||||
@ -2178,7 +2197,9 @@ static int lpc17_40_eth_ioctl(struct net_driver_s *dev, int cmd,
|
||||
|
||||
case SIOCGMIIREG: /* Get register from MII PHY */
|
||||
{
|
||||
struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg);
|
||||
struct mii_ioctl_data_s *req =
|
||||
(struct mii_ioctl_data_s *)((uintptr_t)arg);
|
||||
|
||||
req->val_out = lpc17_40_phyread(priv->lp_phyaddr, req->reg_num);
|
||||
ret = OK;
|
||||
}
|
||||
@ -2186,7 +2207,9 @@ static int lpc17_40_eth_ioctl(struct net_driver_s *dev, int cmd,
|
||||
|
||||
case SIOCSMIIREG: /* Set register in MII PHY */
|
||||
{
|
||||
struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg);
|
||||
struct mii_ioctl_data_s *req =
|
||||
(struct mii_ioctl_data_s *)((uintptr_t)arg);
|
||||
|
||||
lpc17_40_phywrite(priv->lp_phyaddr, req->reg_num, req->val_in);
|
||||
ret = OK;
|
||||
}
|
||||
@ -2313,7 +2336,8 @@ static void lpc17_40_showmii(uint8_t phyaddr, const char *msg)
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef LPC17_40_HAVE_PHY
|
||||
static void lpc17_40_phywrite(uint8_t phyaddr, uint8_t regaddr, uint16_t phydata)
|
||||
static void lpc17_40_phywrite(uint8_t phyaddr, uint8_t regaddr,
|
||||
uint16_t phydata)
|
||||
{
|
||||
uint32_t regval;
|
||||
|
||||
@ -2375,7 +2399,8 @@ static uint16_t lpc17_40_phyread(uint8_t phyaddr, uint8_t regaddr)
|
||||
|
||||
/* Wait for the PHY command to complete */
|
||||
|
||||
while ((lpc17_40_getreg(LPC17_40_ETH_MIND) & (ETH_MIND_BUSY | ETH_MIND_NVALID)) != 0);
|
||||
while ((lpc17_40_getreg(LPC17_40_ETH_MIND) &
|
||||
(ETH_MIND_BUSY | ETH_MIND_NVALID)) != 0);
|
||||
lpc17_40_putreg(0, LPC17_40_ETH_MCMD);
|
||||
|
||||
/* Return the PHY register data */
|
||||
@ -2463,6 +2488,10 @@ static inline int lpc17_40_phyautoneg(uint8_t phyaddr)
|
||||
|
||||
for (timeout = MII_BIG_TIMEOUT; timeout > 0; timeout--)
|
||||
{
|
||||
/* For some motive a large delay is necessary for some PHYs */
|
||||
|
||||
up_udelay(5000);
|
||||
|
||||
/* Check if auto-negotiation has completed */
|
||||
|
||||
phyreg = lpc17_40_phyread(phyaddr, MII_MSR);
|
||||
@ -2534,9 +2563,9 @@ static int lpc17_40_phymode(uint8_t phyaddr, uint8_t mode)
|
||||
|
||||
for (timeout = MII_BIG_TIMEOUT; timeout > 0; timeout--)
|
||||
{
|
||||
/* REVISIT: This should not depend explicity on the board configuration.
|
||||
* Rather, there should be some additional configuration option to
|
||||
* suppress this DP83848C-specific behavior.
|
||||
/* REVISIT: This should not depend explicit y on the board
|
||||
* configuration. Rather, there should be some additional
|
||||
* configuration option to suppress this DP83848C-specific behavior.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_ETH0_PHY_DP83848C) && !defined(CONFIG_ARCH_BOARD_MBED)
|
||||
@ -2668,9 +2697,21 @@ static inline int lpc17_40_phyinit(struct lpc17_40_driver_s *priv)
|
||||
lpc17_40_putreg(regval, LPC17_40_ETH_MCFG);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ETH0_PHY_DP83848C)
|
||||
/* Enable the RMII interface for DP83848x PHYs */
|
||||
|
||||
lpc17_40_phywrite(phyaddr, MII_DP83848C_RBR,
|
||||
MII_RBR_ELAST_2 | MII_RBR_RMIIMODE);
|
||||
#endif
|
||||
|
||||
/* Are we configured to do auto-negotiation? */
|
||||
|
||||
#ifdef CONFIG_LPC17_40_PHY_AUTONEG
|
||||
/* Enable FD mode, Auto-negotiation and 100Mbps speed */
|
||||
|
||||
lpc17_40_phywrite(phyaddr, MII_MCR,
|
||||
MII_MCR_FULLDPLX | MII_MCR_ANENABLE | MII_MCR_SPEED100);
|
||||
|
||||
/* Setup the Auto-negotiation advertisement: 100 or 10, and HD or FD */
|
||||
|
||||
lpc17_40_phywrite(phyaddr, MII_ADVERTISE,
|
||||
@ -2695,6 +2736,15 @@ static inline int lpc17_40_phyinit(struct lpc17_40_driver_s *priv)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ETH0_PHY_DP83848C)
|
||||
/* Wait until the link is established */
|
||||
|
||||
while ((lpc17_40_phyread(phyaddr, MII_DP83848C_STS) & 0x0001) == 0)
|
||||
{
|
||||
up_udelay(40000);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The link is established */
|
||||
|
||||
lpc17_40_showmii(phyaddr, "After link established");
|
||||
@ -2865,16 +2915,18 @@ static inline int lpc17_40_phyinit(struct lpc17_40_driver_s *priv)
|
||||
#endif
|
||||
|
||||
ninfo("%dBase-T %s duplex\n",
|
||||
(priv->lp_mode & LPC17_40_SPEED_MASK) == LPC17_40_SPEED_100 ? 100 : 10,
|
||||
(priv->lp_mode & LPC17_40_DUPLEX_MASK) == LPC17_40_DUPLEX_FULL ?"full" : "half");
|
||||
(priv->lp_mode & LPC17_40_SPEED_MASK) ==
|
||||
LPC17_40_SPEED_100 ? 100 : 10,
|
||||
(priv->lp_mode & LPC17_40_DUPLEX_MASK) ==
|
||||
LPC17_40_DUPLEX_FULL ?"full" : "half");
|
||||
|
||||
/* Disable auto-configuration. Set the fixed speed/duplex mode.
|
||||
* (probably more than little redundant).
|
||||
*
|
||||
* REVISIT: Revisit the following CONFIG_LPC17_40_PHY_CEMENT_DISABLE work-around.
|
||||
* It is should not needed if CONFIG_LPC17_40_PHY_AUTONEG is defined and is known
|
||||
* cause a problem for at least one PHY (DP83848I PHY). It might be
|
||||
* safe just to remove this elided coded for all PHYs.
|
||||
* REVISIT: Revisit the following CONFIG_LPC17_40_PHY_CEMENT_DISABLE work-
|
||||
* around. It is should not needed if CONFIG_LPC17_40_PHY_AUTONEG is
|
||||
* defined and is known cause a problem for at least one PHY (DP83848I
|
||||
* PHY). It might be safe just to remove this elided coded for all PHYs.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_LPC17_40_PHY_CEMENT_DISABLE
|
||||
@ -2920,7 +2972,7 @@ static inline void lpc17_40_txdescinit(struct lpc17_40_driver_s *priv)
|
||||
|
||||
lpc17_40_putreg(LPC17_40_TXDESC_BASE, LPC17_40_ETH_TXDESC);
|
||||
lpc17_40_putreg(LPC17_40_TXSTAT_BASE, LPC17_40_ETH_TXSTAT);
|
||||
lpc17_40_putreg(CONFIG_LPC17_40_ETH_NTXDESC-1, LPC17_40_ETH_TXDESCRNO);
|
||||
lpc17_40_putreg(CONFIG_LPC17_40_ETH_NTXDESC - 1, LPC17_40_ETH_TXDESCRNO);
|
||||
|
||||
/* Initialize Tx descriptors and link to packet buffers */
|
||||
|
||||
@ -2976,7 +3028,7 @@ static inline void lpc17_40_rxdescinit(struct lpc17_40_driver_s *priv)
|
||||
|
||||
lpc17_40_putreg(LPC17_40_RXDESC_BASE, LPC17_40_ETH_RXDESC);
|
||||
lpc17_40_putreg(LPC17_40_RXSTAT_BASE, LPC17_40_ETH_RXSTAT);
|
||||
lpc17_40_putreg(CONFIG_LPC17_40_ETH_NRXDESC-1, LPC17_40_ETH_RXDESCNO);
|
||||
lpc17_40_putreg(CONFIG_LPC17_40_ETH_NRXDESC - 1, LPC17_40_ETH_RXDESCNO);
|
||||
|
||||
/* Initialize Rx descriptors and link to packet buffers */
|
||||
|
||||
@ -3138,8 +3190,8 @@ static void lpc17_40_ethreset(struct lpc17_40_driver_s *priv)
|
||||
lpc17_40_putreg(0, LPC17_40_ETH_TEST);
|
||||
|
||||
lpc17_40_putreg(18, LPC17_40_ETH_IPGR);
|
||||
lpc17_40_putreg(((15 << ETH_CLRT_RMAX_SHIFT) | (55 << ETH_CLRT_COLWIN_SHIFT)),
|
||||
LPC17_40_ETH_CLRT);
|
||||
lpc17_40_putreg(((15 << ETH_CLRT_RMAX_SHIFT) |
|
||||
(55 << ETH_CLRT_COLWIN_SHIFT)), LPC17_40_ETH_CLRT);
|
||||
|
||||
/* Set the Maximum Frame size register. "This field resets to the value
|
||||
* 0x0600, which represents a maximum receive frame of 1536 octets. An
|
||||
|
Loading…
Reference in New Issue
Block a user