arch/arm/src/lpc54xx: Add some Ethernet PHY initialization logic.
This commit is contained in:
parent
31330b2479
commit
cb9e1e7716
@ -671,6 +671,12 @@ endmenu # EMC Configuration
|
||||
menu "Ethernet configuration"
|
||||
depends on LPC54_ETHERNET
|
||||
|
||||
config LPC54_PHYADDR
|
||||
int "PHY address"
|
||||
default 1
|
||||
---help---
|
||||
The 5-bit address of the PHY on the board. Default: 1
|
||||
|
||||
config LPC54_MII
|
||||
bool "Use MII interface"
|
||||
default n
|
||||
|
@ -341,13 +341,42 @@
|
||||
#define ETH_MAC_HW_FEAT2_
|
||||
|
||||
/* MIDO address */
|
||||
#define ETH_MAC_MDIO_ADDR_
|
||||
|
||||
#define ETH_MAC_MDIO_ADDR_MB (1 << 0) /* Bit 0 MII busy */
|
||||
#define ETH_MAC_MDIO_ADDR_MOC_SHIFT (2) /* Bits 2-3: MII operation command */
|
||||
#define ETH_MAC_MDIO_ADDR_MOC_MASK (3 << ETH_MAC_MDIO_ADDR_MOC_SHIFT)
|
||||
# define ETH_MAC_MDIO_ADDR_MOC_WRITE (1 << ETH_MAC_MDIO_ADDR_MOC_SHIFT) /* Write */
|
||||
# define ETH_MAC_MDIO_ADDR_MOC_READ (3 << ETH_MAC_MDIO_ADDR_MOC_SHIFT) /* Read */
|
||||
#define ETH_MAC_MDIO_ADDR_CR_SHIFT (8) /* Bits 8-11: CSR clock range */
|
||||
#define ETH_MAC_MDIO_ADDR_CR_MASK (15 << ETH_MAC_MDIO_ADDR_CR_SHIFT)
|
||||
# define ETH_MAC_MDIO_ADDR_CR_DIV42 (0 << ETH_MAC_MDIO_ADDR_CR_SHIFT) /* CSR=60-100 MHz; MDC=CSR/42 */
|
||||
# define ETH_MAC_MDIO_ADDR_CR_DIV62 (1 << ETH_MAC_MDIO_ADDR_CR_SHIFT) /* CSR=100-150 MHz; MDC=CSR/62 */
|
||||
# define ETH_MAC_MDIO_ADDR_CR_DIV16 (2 << ETH_MAC_MDIO_ADDR_CR_SHIFT) /* CSR=20-35 MHz; MDC=CSR/16 */
|
||||
# define ETH_MAC_MDIO_ADDR_CR_DIV26 (3 << ETH_MAC_MDIO_ADDR_CR_SHIFT) /* CSR=35-60 MHz; MDC=CSR/26 */
|
||||
#define ETH_MAC_MDIO_ADDR_NTC_SHIFT (12) /* Bits 12-14: Number of training clocks */
|
||||
#define ETH_MAC_MDIO_ADDR_NTC_MASK (7 << ETH_MAC_MDIO_ADDR_NTC_SHIFT)
|
||||
# define ETH_MAC_MDIO_ADDR_NTC(n) ((uint32_t)(n) << ETH_MAC_MDIO_ADDR_NTC_SHIFT)
|
||||
#define ETH_MAC_MDIO_ADDR_RDA_SHIFT (16) /* Bits 16-20: Register/device address */
|
||||
#define ETH_MAC_MDIO_ADDR_RDA_MASK (31 << ETH_MAC_MDIO_ADDR_RDA_SHIFT)
|
||||
# define ETH_MAC_MDIO_ADDR_RDA(n) ((uint32_t)(n) << ETH_MAC_MDIO_ADDR_RDA_SHIFT)
|
||||
#define ETH_MAC_MDIO_ADDR_PA_SHIFT (21) /* Bits 21-25: Physical layer address */
|
||||
#define ETH_MAC_MDIO_ADDR_PA_MASK (31 << ETH_MAC_MDIO_ADDR_PA_SHIFT)
|
||||
# define ETH_MAC_MDIO_ADDR_PA(n) ((uint32_t)(n) << ETH_MAC_MDIO_ADDR_PA_SHIFT)
|
||||
#define ETH_MAC_MDIO_ADDR_BTB (1 << 26) /* Bit 26 Back to back transactions */
|
||||
#define ETH_MAC_MDIO_ADDR_PSE (1 << 27) /* Bit 27 Preamble suppression enable */
|
||||
|
||||
/* MDIO data */
|
||||
#define ETH_MAC_MDIO_DATA_
|
||||
|
||||
#define ETH_MAC_MDIO_DATA_MASK 0xffff /* Bits 0-15: 16 bit PHY data */
|
||||
|
||||
/* MAC address0 high */
|
||||
#define ETH_MAC_ADDR_HIGH_
|
||||
/* MAC address0 low */
|
||||
#define ETH_MAC_ADDR_LOW_
|
||||
|
||||
#define ETH_MAC_ADDR_HIGH_A32_47_SHIFT (0) /* MAC address 32-47 */
|
||||
#define ETH_MAC_ADDR_HIGH_A32_47_MASK (0xffff << ETH_MAC_ADDR_HIGH_A32_47_SHIFT)
|
||||
# define ETH_MAC_ADDR_HIGH_A32_47(n) ((uint32_t)(n) << ETH_MAC_ADDR_HIGH_A32_47_SHIFT)
|
||||
#define ETH_MAC_ADDR_HIGH_DCS (1 << 16) /* Bit 16: DMA channel select */
|
||||
|
||||
/* MAC address0 low (32-bit MAC address 0-31) */
|
||||
|
||||
/* Timestamp control */
|
||||
#define ETH_MAC_TIMESTAMP_CTRL_
|
||||
|
@ -701,7 +701,7 @@
|
||||
#define SYSCON_EMCDLYCAL_
|
||||
/* Ethernet PHY selection */
|
||||
|
||||
#define SYSCON_ETHPHYSEL (1 << 2) /* Bit 2: PHY_SEL PHY interface */
|
||||
#define SYSCON_ETHPHYSEL_MASK (1 << 2) /* Bit 2: PHY_SEL PHY interface */
|
||||
# define SYSCON_ETHPHYSEL_MII (0) /* Select MII PHY Interface */
|
||||
# define SYSCON_ETHPHYSEL_RMII (1 << 2) /* Select RMII PHY Interface */
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
@ -53,6 +54,7 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/wdog.h>
|
||||
#include <nuttx/wqueue.h>
|
||||
#include <nuttx/net/mii.h>
|
||||
#include <nuttx/net/arp.h>
|
||||
#include <nuttx/net/netdev.h>
|
||||
|
||||
@ -61,6 +63,7 @@
|
||||
#endif
|
||||
|
||||
#include "up_arch.h"
|
||||
#include "chip/lpc54_syscon.h"
|
||||
#include "chip/lpc54_ethernet.h"
|
||||
#include "lpc54_enableclk.h"
|
||||
#include "lpc54_reset.h"
|
||||
@ -91,6 +94,16 @@
|
||||
|
||||
#define LPC54_TXTIMEOUT (60*CLK_TCK)
|
||||
|
||||
/* PHY-related definitions */
|
||||
|
||||
#define LPC54_PHY_TIMEOUT 0x00ffffff /* Timeout for PHY register accesses */
|
||||
|
||||
#ifdef CONFIG_ETH0_PHY_LAN8720
|
||||
# define LPC54_PHYID1_VAL MII_PHYID1_LAN8720
|
||||
#else
|
||||
# error Unrecognized PHY selection
|
||||
#endif
|
||||
|
||||
/* This is a helper pointer for accessing the contents of the Ethernet header */
|
||||
|
||||
#define BUF ((struct eth_hdr_s *)priv->eth_dev.d_buf)
|
||||
@ -106,6 +119,8 @@
|
||||
struct lpc54_ethdriver_s
|
||||
{
|
||||
bool eth_bifup; /* true:ifup false:ifdown */
|
||||
bool eth_fullduplex; /* true:Full duplex false:Half duplex mode */
|
||||
bool eth_100mbps; /* true:100mbps false:10mbps */
|
||||
WDOG_ID eth_txpoll; /* TX poll timer */
|
||||
WDOG_ID eth_txtimeout; /* TX timeout timer */
|
||||
struct work_s eth_irqwork; /* For deferring interupt work to the work queue */
|
||||
@ -140,10 +155,6 @@ static struct lpc54_ethdriver_s g_ethdriver;
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* PHY_related logic */
|
||||
|
||||
static int lpc54_phy_initialize(FAR struct lpc54_ethdriver_s *priv);
|
||||
|
||||
/* Common TX logic */
|
||||
|
||||
static int lpc54_eth_transmit(FAR struct lpc54_ethdriver_s *priv);
|
||||
@ -189,30 +200,21 @@ static int lpc54_eth_ioctl(FAR struct net_driver_s *dev, int cmd,
|
||||
unsigned long arg);
|
||||
#endif
|
||||
|
||||
/* Initialization/PHY control */
|
||||
|
||||
static void lpc54_set_csrdiv(void);
|
||||
static uint16_t lpc54_phy_read(FAR struct lpc54_ethdriver_s *priv,
|
||||
uint8_t phyreg);
|
||||
static void lpc54_phy_write(FAR struct lpc54_ethdriver_s *priv,
|
||||
uint8_t phyreg, uint16_t phyval);
|
||||
static inline bool lpc54_phy_linkstatus(ENET_Type *base);
|
||||
static int lpc54_phy_autonegotiate(FAR struct lpc54_ethdriver_s *priv);
|
||||
static int lpc54_phy_reset(FAR struct lpc54_ethdriver_s *priv);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_phy_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the PHY.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Reference to the driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int lpc54_phy_initialize(FAR struct lpc54_ethdriver_s *priv)
|
||||
{
|
||||
#warning Missing logic
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_eth_transmit
|
||||
*
|
||||
@ -833,19 +835,16 @@ static int lpc54_eth_ifup(FAR struct net_driver_s *dev)
|
||||
|
||||
/* Initialize the PHY */
|
||||
|
||||
ret = lpc54_phy_initialize(priv);
|
||||
ret = lpc54_phy_autonegotiate(priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: lpc54_phy_initialize failed: %d\n", ret);
|
||||
nerr("ERROR: lpc54_phy_autonegotiate failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize the Ethernet interface, and setup up Ethernet interrupts */
|
||||
#warning Missing logic
|
||||
|
||||
/* Set the Ethernet mode to RMII or MII in the ETHPHYSEL register */
|
||||
#warning Missing logic
|
||||
|
||||
/* Set the sideband flow control for each channel */
|
||||
#warning Missing logic
|
||||
|
||||
@ -890,6 +889,7 @@ static int lpc54_eth_ifdown(FAR struct net_driver_s *dev)
|
||||
{
|
||||
FAR struct lpc54_ethdriver_s *priv = (FAR struct lpc54_ethdriver_s *)dev->d_private;
|
||||
irqstate_t flags;
|
||||
uint32_t regval;
|
||||
|
||||
/* Disable the Ethernet interrupt */
|
||||
|
||||
@ -910,6 +910,28 @@ static int lpc54_eth_ifdown(FAR struct net_driver_s *dev)
|
||||
|
||||
lpc54_reset_eth();
|
||||
|
||||
/* Select MII or RMII mode */
|
||||
|
||||
regval = getreg32(LPC54_SYSCON_ETHPHYSEL);
|
||||
regval &= ~SYSCON_ETHPHYSEL_MASK;
|
||||
#ifdef CONFIG_LPC54_MII
|
||||
retval |= SYSCON_ETHPHYSEL_MII;
|
||||
#else
|
||||
retval |= SYSCON_ETHPHYSEL_RMII;
|
||||
#endif
|
||||
putreg32(regval, LPC54_SYSCON_ETHPHYSEL);
|
||||
|
||||
/* Reset the PHY and bring it to an operational state. We must be capable
|
||||
* of handling PHY ioctl commands while the network is down.
|
||||
*/
|
||||
|
||||
ret = lpc54_phy_reset(priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: lpc54_phy_reset failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Mark the device "down" */
|
||||
|
||||
priv->eth_bifup = false;
|
||||
@ -1156,8 +1178,29 @@ static int lpc54_eth_ioctl(FAR struct net_driver_s *dev, int cmd,
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
/* Add cases here to support the IOCTL commands */
|
||||
#warning Missing logic
|
||||
case SIOCGMIIPHY: /* Get MII PHY address */
|
||||
{
|
||||
struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg);
|
||||
req->phy_id = CONFIG_LPC54_PHYADDR;
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCGMIIREG: /* Get register from MII PHY */
|
||||
{
|
||||
struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg);
|
||||
req->val_out = lpc54_phy_read(priv, req->reg_num);
|
||||
ret = OK
|
||||
}
|
||||
break;
|
||||
|
||||
case SIOCSMIIREG: /* Set register in MII PHY */
|
||||
{
|
||||
struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg);
|
||||
lpc54_phy_write(priv, req->reg_num, req->val_in);
|
||||
ret = OK
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
nerr("ERROR: Unrecognized IOCTL command: %d\n", command);
|
||||
@ -1168,6 +1211,288 @@ static int lpc54_eth_ioctl(FAR struct net_driver_s *dev, int cmd,
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_set_csrdiv
|
||||
*
|
||||
* Description:
|
||||
* Set the CSR clock divider. The MDC clock derives from the divided down
|
||||
* CSR clock (aka core clock or main clock).
|
||||
*
|
||||
* Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void lpc54_set_csrdiv(void)
|
||||
{
|
||||
uint32_t srcclk = BOARD_MAIN_CLK / 1000000;
|
||||
uint32_t regval;
|
||||
|
||||
regval = getreg32(LPC54_ETH_MAC_MDIO_ADDR);
|
||||
regval &= ~ETH_MAC_MDIO_ADDR_CR_MASK;
|
||||
|
||||
if (srcclk < 35)
|
||||
{
|
||||
regval |= ETH_MAC_MDIO_ADDR_CR_DIV16; /* CSR=20-35 MHz; MDC=CSR/16 */
|
||||
}
|
||||
else if (srcclk < 60)
|
||||
{
|
||||
regval |= ETH_MAC_MDIO_ADDR_CR_DIV26; /* CSR=35-60 MHz; MDC=CSR/26 */
|
||||
}
|
||||
else if (srcclk < 100)
|
||||
{
|
||||
regval |= ETH_MAC_MDIO_ADDR_CR_ DIV42; /* CSR=60-100 MHz; MDC=CSR/42 */
|
||||
}
|
||||
else /* if (srcclk < 150) */
|
||||
{
|
||||
regval |= ETH_MAC_MDIO_ADDR_CR_DIV62; /* CSR=100-150 MHz; MDC=CSR/62 */
|
||||
}
|
||||
|
||||
putreg32(regval, LPC54_ETH_MAC_MDIO_ADDR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_phy_read
|
||||
*
|
||||
* Description:
|
||||
* Read the content from one PHY register.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Reference to the driver state structure
|
||||
* phyreg - The 5-bit PHY address to read
|
||||
*
|
||||
* Returned Value:
|
||||
* The 16-bit value read from the specified PHY register
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint16_t lpc54_phy_read(FAR struct lpc54_ethdriver_s *priv,
|
||||
uint8_t phyreg)
|
||||
{
|
||||
uint32_t regval = base->MAC_MDIO_ADDR & ENET_MAC_MDIO_ADDR_CR_MASK;
|
||||
|
||||
/* Set the MII read command. */
|
||||
|
||||
regval = getreg32(LPC54_ETH_MAC_MDIO_ADDR);
|
||||
regval &= ETH_MAC_MDIO_ADDR_CR_MASK;
|
||||
regval |= ETH_MAC_MDIO_ADDR_MOC_READ | ETH_MAC_MDIO_ADDR_RDA(phyreg) |
|
||||
ETH_MAC_MDIO_ADDR_PA(CONFIG_LPC54_PHYADDR);
|
||||
putreg32(regval, LPC54_ETH_MAC_MDIO_ADDR);
|
||||
|
||||
/* Initiate the read */
|
||||
|
||||
regval |= ETH_MAC_MDIO_ADDR_MB;
|
||||
putreg32(regval, LPC54_ETH_MAC_MDIO_ADDR);
|
||||
|
||||
/* Wait until the SMI is no longer busy with the read */
|
||||
|
||||
while ((getreg32(LPC54_ETH_MAC_MDIO_ADDR) & ETH_MAC_MDIO_ADDR_MB) != 0)
|
||||
{
|
||||
}
|
||||
|
||||
return (uint16_t)getreg32(LPC54_ETH_MAC_MDIO_DATA);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_phy_write
|
||||
*
|
||||
* Description:
|
||||
* Write a new value to of one PHY register.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Reference to the driver state structure
|
||||
* phyreg - The 5-bit PHY address to write
|
||||
* phyval - The 16-bit value to write to the PHY register
|
||||
*
|
||||
* Returned Value:
|
||||
* The 16-bit value read from the specified PHY register
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void lpc54_phy_write(FAR struct lpc54_ethdriver_s *priv,
|
||||
uint8_t phyreg, uint16_t phyval)
|
||||
{
|
||||
uint32_t regval = base->MAC_MDIO_ADDR & ENET_MAC_MDIO_ADDR_CR_MASK;
|
||||
|
||||
/* Set the MII write command. */
|
||||
|
||||
regval = getreg32(LPC54_ETH_MAC_MDIO_ADDR);
|
||||
regval &= ETH_MAC_MDIO_ADDR_CR_MASK;
|
||||
regval |= ETH_MAC_MDIO_ADDR_MOC_WRITE | ETH_MAC_MDIO_ADDR_RDA(phyreg) |
|
||||
ETH_MAC_MDIO_ADDR_PA(CONFIG_LPC54_PHYADDR);
|
||||
putreg32(regval, LPC54_ETH_MAC_MDIO_ADDR);
|
||||
|
||||
/* Set the write data */
|
||||
|
||||
putreg32((uint32_t)phyval, LPC54_ETH_MAC_MDIO_DATA);
|
||||
|
||||
/* Initiate the write */
|
||||
|
||||
regval |= ETH_MAC_MDIO_ADDR_MB;
|
||||
putreg32(regval, LPC54_ETH_MAC_MDIO_ADDR);
|
||||
|
||||
/* Wait until the SMI is no longer busy with the write */
|
||||
|
||||
while ((getreg32(LPC54_ETH_MAC_MDIO_ADDR) & ETH_MAC_MDIO_ADDR_MB) != 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_phy_linkstatus
|
||||
*
|
||||
* Description:
|
||||
* Read the MII status register and return tru if the link is up.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Reference to the driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* true if the link is up
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline bool lpc54_phy_linkstatus(ENET_Type *base)
|
||||
{
|
||||
/* Read the status register and return tru of the linkstatus bit is set. */
|
||||
|
||||
return ((lpc54_phy_read(priv, MII_MSR) & MII_MSR_LINKSTATUS) != 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_phy_autonegotiate
|
||||
*
|
||||
* Description:
|
||||
* Initialize the PHY.
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Reference to the driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int lpc54_phy_autonegotiate(FAR struct lpc54_ethdriver_s *priv)
|
||||
{
|
||||
volatile int32_t timeout;
|
||||
uint16_t phyid1;
|
||||
uint16_t phyval;
|
||||
|
||||
/* Advertise our cabilities. */
|
||||
|
||||
phyval = (MII_ADVERTISE_CSMA | MII_ADVERTISE_10BASETXHALF |
|
||||
MII_ADVERTISE_10BASETXFULL | MII_ADVERTISE_100BASETXHALF |
|
||||
MII_ADVERTISE_100BASETXFULL);
|
||||
lpc54_phy_write(priv, MII_ADVERTISE, phyval);
|
||||
|
||||
/* Start Auto negotiation and wait until auto negotiation completion */
|
||||
|
||||
phyval = (MII_MCR_ANENABLE | MII_MCR_ANRESTART);
|
||||
lpc54_phy_write(priv, MII_MCR, phyval);
|
||||
|
||||
/* Wait for the completion of autonegotiation. */
|
||||
|
||||
#ifdef CONFIG_ETH0_PHY_LAN8720
|
||||
timeout = LPC54_PHY_TIMEOUT;
|
||||
do
|
||||
{
|
||||
if (timeout-- <= 0)
|
||||
{
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
phyval = lpc54_phy_read(priv, MII_LAN8720_SCSR);
|
||||
|
||||
}
|
||||
while ((phyval & MII_LAN8720_SPSCR_ANEGDONE) == 0);
|
||||
#else
|
||||
# error Unrecognized PHY
|
||||
#endif
|
||||
|
||||
/* Wait for the link to be in the UP state */
|
||||
|
||||
timeout = LPC54_PHY_TIMEOUT;
|
||||
do
|
||||
{
|
||||
if (timeout-- <= 0)
|
||||
{
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
while (!lpc54_phy_linkstatus(priv));
|
||||
|
||||
/* Get the negotiate PHY link mode. */
|
||||
|
||||
#ifdef CONFIG_ETH0_PHY_LAN8720
|
||||
/* Read the LAN8720 SPCR register. */
|
||||
|
||||
phyval = lpc54_phy_read(priv, MII_LAN8720_SCSR);
|
||||
priv->eth_fullduplex = ((phyval & MII_LAN8720_SPSCR_DUPLEX) != 0);
|
||||
priv->eth_100mbps = ((phyval & MII_LAN8720_SPSCR_100MBPS) != 0);
|
||||
#else
|
||||
# error Unrecognized PHY
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lpc54_phy_reset
|
||||
*
|
||||
* Description:
|
||||
* Reset the PHY and bring it to the operational status
|
||||
*
|
||||
* Parameters:
|
||||
* priv - Reference to the driver state structure
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int lpc54_phy_reset(FAR struct lpc54_ethdriver_s *priv)
|
||||
{
|
||||
volatile int32_t timeout;
|
||||
uint16_t phyid1;
|
||||
uint16_t phyval;
|
||||
|
||||
/* Read and verify the PHY ID1 register */
|
||||
|
||||
timeout = LPC54_PHY_TIMEOUT;
|
||||
do
|
||||
{
|
||||
if (timeout-- <= 0)
|
||||
{
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
phyid1 = lpc54_phy_read(priv, MII_PHYID1);
|
||||
}
|
||||
while (phyid1 != LPC54_PHYID1_VAL);
|
||||
|
||||
/* Reset PHY and wait until completion. */
|
||||
|
||||
lpc54_phy_write(priv, MII_MCR, MII_MCR_RESET);
|
||||
|
||||
timeout = LPC54_PHY_TIMEOUT;
|
||||
do
|
||||
{
|
||||
if (timeout-- <= 0)
|
||||
{
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
phyval = lpc54_phy_read(base, CONFIG_LPC54_PHYADDR, MII_MCR, ®);
|
||||
}
|
||||
while ((phyval & MII_MCR_RESET) != 0);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -1207,6 +1532,7 @@ int up_netinitialize(int intf)
|
||||
{
|
||||
/* We could not attach the ISR to the interrupt */
|
||||
|
||||
nerr("ERROR: irq_attach failed\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
@ -1258,7 +1584,11 @@ int up_netinitialize(int intf)
|
||||
lpc54_gpio_config(GPIO_ENET_TX_ER); /* Ethernet receive error */
|
||||
lpc54_gpio_config(GPIO_ENET_TX_EN); /* Ethernet transmit enable */
|
||||
#else
|
||||
/* RMII interface */
|
||||
/* RMII interface.
|
||||
*
|
||||
* REF_CLK may be available in some implementations
|
||||
* RX_ER is optional on switches
|
||||
*/
|
||||
|
||||
lpc54_gpio_config(GPIO_ENET_RXD0); /* Ethernet receive data 0-1 */
|
||||
lpc54_gpio_config(GPIO_ENET_RXD1);
|
||||
@ -1272,6 +1602,10 @@ int up_netinitialize(int intf)
|
||||
|
||||
lpc54_eth_enableclk();
|
||||
|
||||
/* Set the CSR clock divider */
|
||||
|
||||
lpc43_set_crsdiv();
|
||||
|
||||
/* Put the interface in the down state. This amounts to resetting the
|
||||
* device by calling lpc54_eth_ifdown().
|
||||
*/
|
||||
@ -1279,6 +1613,7 @@ int up_netinitialize(int intf)
|
||||
ret = lpc54_eth_ifdown(&priv->eth_dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: lpc54_eth_ifdown failed: %d\n", ret);
|
||||
goto errout_with_clock;
|
||||
}
|
||||
|
||||
@ -1287,6 +1622,7 @@ int up_netinitialize(int intf)
|
||||
ret = netdev_register(&priv->eth_dev, NET_LL_ETHERNET);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: netdev_register failed: %d\n", ret);
|
||||
goto errout_with_clock:
|
||||
}
|
||||
|
||||
|
@ -383,6 +383,48 @@
|
||||
|
||||
#define GPIO_LCD_VD3 GPIO_LCD_VD3_1
|
||||
|
||||
/* Ethernet Clock
|
||||
*
|
||||
* The Lpcxpresso-LPC546258 uses a LAN8720A PHY in RMII mode. Clocking is
|
||||
* provided via a 25MHz crystal (Y1). CLKOUT on P3.12 is an option if JS4
|
||||
* is reversed.
|
||||
*/
|
||||
|
||||
#define BOARD_PHY_CLOCK 25000000 /* 25MHz crystal */
|
||||
|
||||
/* Ethernet RMII mode pins:
|
||||
*
|
||||
* P4_16-ENET_MDIO Ethernet MIIM data input and output
|
||||
* P4_15-ENET_MDC Ethernet MIIM clock
|
||||
*
|
||||
* P4_11-ENET_RXD0 Ethernet receive data 0-1
|
||||
* P4_12-ENET_RXD1
|
||||
* P4_8-ENET_TXD0 Ethernet transmit data 0-1
|
||||
* P0_17-ENET_TXD1
|
||||
* P4_10-ENET_CRS_DV Ethernet receive data valid
|
||||
* P4_13-ENET_TX_EN Ethernet transmit data enable
|
||||
*
|
||||
* P4_14-ENET_RX_CLK REF_CLK, Reference clock (Not used)
|
||||
* P2_26-ENET_PHY_RSTn nRST (Controlled by board logic)
|
||||
*
|
||||
* NOTE: You must set JP11 and JP12 to close 1-2 to enable Ethernet
|
||||
* port functionality. Some pins are shared with USB0 overcurrent
|
||||
* feature.
|
||||
*/
|
||||
|
||||
|
||||
#define GPIO_ENET_MDIO GPIO_ENET_MDIO_2 /* P4.16 */
|
||||
#define GPIO_ENET_MDC GPIO_ENET_MDC_2 /* P4.15 */
|
||||
|
||||
#define GPIO_ENET_RXD0 GPIO_ENET_RXD0_2 /* P4.11 */
|
||||
#define GPIO_ENET_RXD1 GPIO_ENET_RXD1_2 /* P4.12 */
|
||||
#define GPIO_ENET_TXD0 GPIO_ENET_TXD0_3 /* P4.8 */
|
||||
#define GPIO_ENET_TXD1 GPIO_ENET_TXD1_4 /* P0.17 */
|
||||
#define GPIO_ENET_RX_DV GPIO_ENET_RX_DV_2 /* P4.10 */
|
||||
#define GPIO_ENET_TX_EN GPIO_ENET_TX_EN_2 /* P4.13 */
|
||||
|
||||
#define GPIO_ENET_RX_CLK GPIO_ENET_RX_CLK_2 /* P4.14 */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
@ -351,6 +351,14 @@
|
||||
#define MII_PHYID1_LAN8720 0x0007 /* ID1 value for LAN8720 */
|
||||
#define MII_PHYID2_LAN8720 0xc0f1 /* ID2 value for LAN8720 */
|
||||
|
||||
/* SMSC LAN8720 SPCR register bits */
|
||||
|
||||
#define MII_LAN8720_SPSCR_10MBPS (1 << 2) /* Bit 2: 10MBPS speed */
|
||||
#define MII_LAN8720_SPSCR_100MBPS (1 << 3) /* Bit 3: 100MBPS speed */
|
||||
#define MII_LAN8720_SPSCR_DUPLEX (1 << 4) /* Bit 4: Duplex mode */
|
||||
#define MII_LAN8720_SPSCR_MODEMASK 0x1c /* Mode/speed mask */
|
||||
#define MII_LAN8720_SPSCR_ANEGDONE (1 << 12) /* Bit 12: Autonegotiation complete */
|
||||
|
||||
/* SMSC LAN8740 MII ID1/2 register bits */
|
||||
|
||||
#define MII_PHYID1_LAN8740 0x0007 /* ID1 value for LAN8740 */
|
||||
|
Loading…
Reference in New Issue
Block a user