arch/arm/src/lpc54xx: Add register level debug output for Ethernet testing. Fixed a few start up problems. Still hangs on start-up, however.

This commit is contained in:
Gregory Nutt 2017-12-31 11:11:57 -06:00
parent 63c055e1ee
commit b2adb4917f
10 changed files with 240 additions and 100 deletions

View file

@ -254,11 +254,9 @@ struct lpc43_dev_s
#ifdef CONFIG_LPC43_SDMMC_REGDEBUG
static uint32_t lpc43_getreg(uint32_t addr);
static void lpc43_putreg(uint32_t val, uint32_t addr);
static void lpc43_checksetup(void);
#else
# define lpc43_getreg(addr) getreg32(addr)
# define lpc43_putreg(val,addr) putreg32(val,addr)
# define lpc43_checksetup()
#endif
/* Low-level helpers ********************************************************/

View file

@ -862,6 +862,13 @@ config LPC54_ETH_NTXDESC1
NOTE: Each Rx descriptor will require a transmit buffer at the size
of the configured MTU.
config LPC54_ETH_REGDEBUG
bool "Register level debug"
default n
depends on DEBUG_NET_INFO
---help---
Output detailed register-level Ethernet debug information.
endmenu # Ethernet configuration
menu "SD/MMC Configuration"

View file

@ -363,6 +363,16 @@ static uint32_t *g_txbuffers1[CONFIG_LPC54_ETH_NTXDESC1];
* Private Function Prototypes
****************************************************************************/
/* Register level debug hooks */
#ifdef CONFIG_LPC54_ETH_REGDEBUG
static uint32_t lpc54_getreg(uintptr_t addr);
static void lpc54_putreg(uint32_t val, uintptr_t addr);
#else
# define lpc54_getreg(addr) getreg32(addr)
# define lpc54_putreg(val,addr) lpc54_putreg(val,addr)
#endif
/* Common TX logic */
static int lpc54_eth_transmit(struct lpc54_ethdriver_s *priv,
@ -447,6 +457,107 @@ static int lpc54_phy_reset(struct lpc54_ethdriver_s *priv);
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: lpc54_getreg
*
* Description:
* This function may to used to intercept an monitor all register accesses.
* Clearly this is nothing you would want to do unless you are debugging
* this driver.
*
* Input Parameters:
* addr - The register address to read
*
* Returned Value:
* The value read from the register
*
****************************************************************************/
#ifdef CONFIG_LPC54_ETH_REGDEBUG
static uint32_t lpc54_getreg(uintptr_t addr)
{
static uintptr_t prevaddr = 0;
static uint32_t preval = 0;
static uint32_t count = 0;
/* Read the value from the register */
uint32_t val = getreg32(addr);
/* Is this the same value that we read from the same register last time?
* Are we polling the register? If so, suppress some of the output.
*/
if (addr == prevaddr && val == preval)
{
if (count == 0xffffffff || ++count > 3)
{
if (count == 4)
{
ninfo("...\n");
}
return val;
}
}
/* No this is a new address or value */
else
{
/* Did we print "..." for the previous value? */
if (count > 3)
{
/* Yes.. then show how many times the value repeated */
ninfo("[repeats %d more times]\n", count-3);
}
/* Save the new address, value, and count */
prevaddr = addr;
preval = val;
count = 1;
}
/* Show the register value read */
ninfo("%08x->%08x\n", addr, val);
return val;
}
#endif
/****************************************************************************
* Name: lpc54_putreg
*
* Description:
* This function may to used to intercept an monitor all register accesses.
* Clearly this is nothing you would want to do unless you are debugging
* this driver.
*
* Input Parameters:
* val - The value to write to the register
* addr - The register address to read
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_LPC54_ETH_REGDEBUG
static void lpc54_putreg(uint32_t val, uintptr_t addr)
{
/* Show the register value being written */
ninfo("%08x<-%08x\n", addr, val);
/* Write the value */
putreg32(val, addr);
}
#endif
/****************************************************************************
* Name: lpc54_eth_transmit
*
@ -563,7 +674,7 @@ static int lpc54_eth_transmit(struct lpc54_ethdriver_s *priv,
/* Update the DMA tail pointer */
putreg32((uint32_t)txdesc, LPC54_ETH_DMACH_TXDESC_TAIL_PTR(chan));
lpc54_putreg((uint32_t)txdesc, LPC54_ETH_DMACH_TXDESC_TAIL_PTR(chan));
/* Setup the TX timeout watchdog (perhaps restarting the timer) */
@ -911,7 +1022,7 @@ static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
/* If no Rx descriptor is available, then suspend for now */
regval = getreg32(LPC54_ETH_DMACH_STAT(chan));
regval = lpc54_getreg(LPC54_ETH_DMACH_STAT(chan));
suspend = ((regval & ETH_DMACH_INT_RBU) != 0);
/* Loop until the last received frame is encountered */
@ -1034,8 +1145,8 @@ static void lpc54_eth_receive(struct lpc54_ethdriver_s *priv,
{
uintptr_t regaddr = LPC54_ETH_DMACH_RXDESC_TAIL_PTR(chan);
regval = getreg32(regaddr);
putreg32(regval, regaddr);
regval = lpc54_getreg(regaddr);
lpc54_putreg(regval, regaddr);
}
}
@ -1153,7 +1264,7 @@ static void lpc54_eth_channel_work(struct lpc54_ethdriver_s *priv,
/* Read the DMA status register for this channel */
regaddr = LPC54_ETH_DMACH_STAT(chan);
status = getreg32(regaddr);
status = lpc54_getreg(regaddr);
/* Check for abnormal interrupts */
@ -1161,11 +1272,13 @@ static void lpc54_eth_channel_work(struct lpc54_ethdriver_s *priv,
{
/* Acknowledge the normal receive interrupt */
putreg32(LPC54_ABNORM_INTMASK, regaddr);
lpc54_putreg(LPC54_ABNORM_INTMASK, regaddr);
/* Handle the incoming packet */
nerr("ERROR: Abnormal interrupt received: %08lx\n", (unsigned long)status);
nerr("ERROR: Abnormal interrupt received: %08lx\n",
(unsigned long)status);
status &= ~LPC54_ABNORM_INTMASK;
/* Check for Tx/Rx related errors and update statistics */
@ -1187,7 +1300,7 @@ static void lpc54_eth_channel_work(struct lpc54_ethdriver_s *priv,
{
/* Acknowledge the normal receive interrupt */
putreg32(ETH_DMACH_INT_RI | ETH_DMACH_INT_NI, regaddr);
lpc54_putreg(ETH_DMACH_INT_RI | ETH_DMACH_INT_NI, regaddr);
status &= ~(ETH_DMACH_INT_RI | ETH_DMACH_INT_NI);
/* Update statistics */
@ -1205,7 +1318,7 @@ static void lpc54_eth_channel_work(struct lpc54_ethdriver_s *priv,
{
/* Acknowledge the normal receive interrupt */
putreg32(ETH_DMACH_INT_TI | ETH_DMACH_INT_NI, regaddr);
lpc54_putreg(ETH_DMACH_INT_TI | ETH_DMACH_INT_NI, regaddr);
status &= ~(ETH_DMACH_INT_TI | ETH_DMACH_INT_NI);
/* Handle the Tx completion event. Reclaim the completed Tx
@ -1222,7 +1335,7 @@ static void lpc54_eth_channel_work(struct lpc54_ethdriver_s *priv,
{
nwarn("WARNING: Unhandled interrupts: %08lx\n",
(unsigned int)status);
putreg32(status, regaddr);
lpc54_putreg(status, regaddr);
}
}
@ -1254,7 +1367,7 @@ static void lpc54_eth_interrupt_work(void *arg)
/* Check if interrupt is from DMA channel 0. */
intrstat = getreg32(LPC54_ETH_DMA_INTR_STAT);
intrstat = lpc54_getreg(LPC54_ETH_DMA_INTR_STAT);
if ((intrstat & ETH_DMA_INTR_STAT_DC0IS) != 0)
{
lpc54_eth_channel_work(priv, 0);
@ -1262,7 +1375,7 @@ static void lpc54_eth_interrupt_work(void *arg)
/* Check if interrupt is from DMA channel 1. */
intrstat = getreg32(LPC54_ETH_DMA_INTR_STAT);
intrstat = lpc54_getreg(LPC54_ETH_DMA_INTR_STAT);
if ((intrstat & ETH_DMA_INTR_STAT_DC1IS) != 0)
{
lpc54_eth_channel_work(priv, 1);
@ -1690,13 +1803,13 @@ static int lpc54_eth_ifup(struct net_driver_s *dev)
/* Initialize Ethernet DMA ************************************************/
/* Reset DMA */
regval = getreg32(LPC54_ETH_DMA_MODE);
regval = lpc54_getreg(LPC54_ETH_DMA_MODE);
regval |= ETH_DMA_MODE_SWR;
putreg32(regval, LPC54_ETH_DMA_MODE);
lpc54_putreg(regval, LPC54_ETH_DMA_MODE);
/* Wait for the reset bit to be cleared at the completion of the reset */
while ((getreg32(LPC54_ETH_DMA_MODE) & ETH_DMA_MODE_SWR) != 0)
while ((lpc54_getreg(LPC54_ETH_DMA_MODE) & ETH_DMA_MODE_SWR) != 0)
{
}
@ -1705,29 +1818,29 @@ static int lpc54_eth_ifup(struct net_driver_s *dev)
for (i = 0; i < LPC54_NRINGS; i++)
{
base = LPC54_ETH_DMACH_CTRL_BASE(i);
putreg32(LPC54_PBLx8, base + LPC54_ETH_DMACH_CTRL_OFFSET);
lpc54_putreg(LPC54_PBLx8, base + LPC54_ETH_DMACH_CTRL_OFFSET);
regval = getreg32(base + LPC54_ETH_DMACH_TX_CTRL_OFFSET);
regval = lpc54_getreg(base + LPC54_ETH_DMACH_TX_CTRL_OFFSET);
regval &= ~ETH_DMACH_TX_CTRL_TxPBL_MASK;
regval |= ETH_DMACH_TX_CTRL_TxPBL(LPC54_BURSTLEN);
putreg32(regval, base + LPC54_ETH_DMACH_TX_CTRL_OFFSET);
lpc54_putreg(regval, base + LPC54_ETH_DMACH_TX_CTRL_OFFSET);
regval = getreg32(base + LPC54_ETH_DMACH_RX_CTRL_OFFSET);
regval = lpc54_getreg(base + LPC54_ETH_DMACH_RX_CTRL_OFFSET);
regval &= ~ETH_DMACH_RX_CTRL_RxPBL_MASK;
regval |= ETH_DMACH_RX_CTRL_RxPBL(LPC54_BURSTLEN);
putreg32(regval, base + LPC54_ETH_DMACH_RX_CTRL_OFFSET);
lpc54_putreg(regval, base + LPC54_ETH_DMACH_RX_CTRL_OFFSET);
}
/* Initializes the Ethernet MTL *******************************************/
#ifdef CONFIG_LPC54_ETH_MULTIQUEUE
/* Set the schedule/arbitration for multiple queues */
putreg32(LPC54_MTL_OPMODE_SCHALG | LPC54_MTL_OPMODE_RAA,
LPC54_ETH_MTL_OP_MODE);
lpc54_putreg(LPC54_MTL_OPMODE_SCHALG | LPC54_MTL_OPMODE_RAA,
LPC54_ETH_MTL_OP_MODE);
/* Set the Rx queue mapping to DMA channel. */
putreg32(LPC54_QUEUEMAP, LPC54_ETH_MTL_RXQ_DMA_MAP);
lpc54_putreg(LPC54_QUEUEMAP, LPC54_ETH_MTL_RXQ_DMA_MAP);
#endif
/* Set transmit queue operation mode
@ -1747,14 +1860,14 @@ static int lpc54_eth_ifup(struct net_driver_s *dev)
regval |= ETH_MTL_TXQ_OP_MODE_FTQ | ETH_MTL_TXQ_OP_MODE_TTC_32 |
ETH_MTL_TXQ_OP_MODE_TQS(LPC54_MTL_TXQUEUE_UNITS);
putreg32(regval | ETH_MTL_TXQ_OP_MODE_TXQEN_ENABLE,
LPC54_ETH_MTL_TXQ_OP_MODE(0));
lpc54_putreg(regval | ETH_MTL_TXQ_OP_MODE_TXQEN_ENABLE,
LPC54_ETH_MTL_TXQ_OP_MODE(0));
#ifdef CONFIG_LPC54_ETH_MULTIQUEUE
putreg32(regval | ETH_MTL_TXQ_OP_MODE_TXQEN_ENABLE,
LPC54_ETH_MTL_TXQ_OP_MODE(1));
lpc54_putreg(regval | ETH_MTL_TXQ_OP_MODE_TXQEN_ENABLE,
LPC54_ETH_MTL_TXQ_OP_MODE(1));
#else
putreg32(regval | ETH_MTL_TXQ_OP_MODE_TXQEN_DISABLE,
LPC54_ETH_MTL_TXQ_OP_MODE(1));
lpc54_putreg(regval | ETH_MTL_TXQ_OP_MODE_TXQEN_DISABLE,
LPC54_ETH_MTL_TXQ_OP_MODE(1));
#endif
/* Set receive receive operation mode
@ -1775,17 +1888,17 @@ static int lpc54_eth_ifup(struct net_driver_s *dev)
regval |= ETH_MTL_RXQ_OP_MODE_RTC_64 | ETH_MTL_RXQ_OP_MODE_FUP |
ETH_MTL_RXQ_OP_MODE_RQS(LPC54_MTL_RXQUEUE_UNITS);
putreg32(regval, LPC54_ETH_MTL_RXQ_OP_MODE(0));
lpc54_putreg(regval, LPC54_ETH_MTL_RXQ_OP_MODE(0));
#ifdef CONFIG_LPC54_ETH_MULTIQUEUE
putreg32(regval, LPC54_ETH_MTL_RXQ_OP_MODE(1));
lpc54_putreg(regval, LPC54_ETH_MTL_RXQ_OP_MODE(1));
/* Set the Tx/Rx queue weights. */
putreg32(CONFIG_LPC54_ETH_TXQ0WEIGHT, LPC54_ETH_MTL_TXQ_QNTM_WGHT(0));
putreg32(CONFIG_LPC54_ETH_TXQ1WEIGHT, LPC54_ETH_MTL_TXQ_QNTM_WGHT(1));
lpc54_putreg(CONFIG_LPC54_ETH_TXQ0WEIGHT, LPC54_ETH_MTL_TXQ_QNTM_WGHT(0));
lpc54_putreg(CONFIG_LPC54_ETH_TXQ1WEIGHT, LPC54_ETH_MTL_TXQ_QNTM_WGHT(1));
putreg32(CONFIG_LPC54_ETH_RXQ0WEIGHT, LPC54_ETH_MTL_RXQ_CTRL(0));
putreg32(CONFIG_LPC54_ETH_RXQ1WEIGHT, LPC54_ETH_MTL_RXQ_CTRL(1));
lpc54_putreg(CONFIG_LPC54_ETH_RXQ0WEIGHT, LPC54_ETH_MTL_RXQ_CTRL(0));
lpc54_putreg(CONFIG_LPC54_ETH_RXQ1WEIGHT, LPC54_ETH_MTL_RXQ_CTRL(1));
#endif
/* Initialize the Ethernet MAC ********************************************/
@ -1796,10 +1909,10 @@ static int lpc54_eth_ifup(struct net_driver_s *dev)
mptr = (uint8_t *)priv->eth_dev.d_mac.ether.ether_addr_octet;
regval = ((uint32_t)mptr[3] << 24) | ((uint32_t)mptr[2] << 16) |
((uint32_t)mptr[1] << 8) | ((uint32_t)mptr[0]);
putreg32(regval, LPC54_ETH_MAC_ADDR_LOW);
lpc54_putreg(regval, LPC54_ETH_MAC_ADDR_LOW);
regval = ((uint32_t)mptr[5] << 8) | ((uint32_t)mptr[4]);
putreg32(regval, LPC54_ETH_MAC_ADDR_LOW);
lpc54_putreg(regval, LPC54_ETH_MAC_ADDR_LOW);
/* Set the receive address filter */
@ -1813,23 +1926,23 @@ static int lpc54_eth_ifup(struct net_driver_s *dev)
#ifdef LPC54_ACCEPT_ALLMULTICAST
regval |= ETH_MAC_FRAME_FILTER_PM;
#endif
putreg32(regval, LPC54_ETH_MAC_FRAME_FILTER);
lpc54_putreg(regval, LPC54_ETH_MAC_FRAME_FILTER);
#ifdef CONFIG_LPC54_ETH_FLOWCONTROL
/* Configure flow control */
regval = ETH_MAC_RX_FLOW_CTRL_RFE | ETH_MAC_RX_FLOW_CTRL_UP;
putreg32(regval, LPC54_ETH_MAC_RX_FLOW_CTRL);
lpc54_putreg(regval, LPC54_ETH_MAC_RX_FLOW_CTRL);
regval = ETH_MAC_TX_FLOW_CTRL_Q_PT(CONFIG_LPC54_ETH_TX_PAUSETIME);
putreg32(regval, LPC54_ETH_MAC_TX_FLOW_CTRL_Q0);
putreg32(regval, LPC54_ETH_MAC_TX_FLOW_CTRL_Q1);
lpc54_putreg(regval, LPC54_ETH_MAC_TX_FLOW_CTRL_Q0);
lpc54_putreg(regval, LPC54_ETH_MAC_TX_FLOW_CTRL_Q1);
#endif
/* Set the 1uS tick counter*/
regval = ETH_MAC_1US_TIC_COUNTR(BOARD_MAIN_CLK / USEC_PER_SEC);
putreg32(regval, LPC54_ETH_MAC_1US_TIC_COUNTR);
lpc54_putreg(regval, LPC54_ETH_MAC_1US_TIC_COUNTR);
/* Set the speed and duplex using the values previously determined through
* autonegotiaion.
@ -1855,7 +1968,7 @@ static int lpc54_eth_ifup(struct net_driver_s *dev)
regval |= ETH_MAC_CONFIG_FES;
}
putreg32(regval, LPC54_ETH_MAC_CONFIG);
lpc54_putreg(regval, LPC54_ETH_MAC_CONFIG);
/* REVISIT: The User Manual says we need to set the SYSCON sideband flow
* control for each channel. But it is not clear to me what setting that
@ -1866,15 +1979,15 @@ static int lpc54_eth_ifup(struct net_driver_s *dev)
regval = ETH_MAC_RXQ_CTRL0_RXQ0EN_ENABLE |
ETH_MAC_RXQ_CTRL0_RXQ1EN_ENABLE;
putreg32(regval, LPC54_ETH_MAC_RXQ_CTRL0);
lpc54_putreg(regval, LPC54_ETH_MAC_RXQ_CTRL0);
/* Setup up Ethernet interrupts */
regval = LPC54_NORM_INTMASK | LPC54_ABNORM_INTMASK;
putreg32(regval, LPC54_ETH_DMACH_INT_EN(0));
putreg32(regval, LPC54_ETH_DMACH_INT_EN(1));
lpc54_putreg(regval, LPC54_ETH_DMACH_INT_EN(0));
lpc54_putreg(regval, LPC54_ETH_DMACH_INT_EN(1));
putreg32(0, LPC54_ETH_MAC_INTR_EN);
lpc54_putreg(0, LPC54_ETH_MAC_INTR_EN);
/* Initialize packet buffers */
@ -1886,22 +1999,22 @@ static int lpc54_eth_ifup(struct net_driver_s *dev)
/* Activate DMA on channel 0 */
regval = getreg32(LPC54_ETH_DMACH_RX_CTRL(0));
regval = lpc54_getreg(LPC54_ETH_DMACH_RX_CTRL(0));
regval |= ETH_DMACH_RX_CTRL_SR;
putreg32(regval, LPC54_ETH_DMACH_RX_CTRL(0));
lpc54_putreg(regval, LPC54_ETH_DMACH_RX_CTRL(0));
regval = getreg32(LPC54_ETH_DMACH_TX_CTRL(0));
regval = lpc54_getreg(LPC54_ETH_DMACH_TX_CTRL(0));
regval |= ETH_DMACH_TX_CTRL_ST;
putreg32(regval, LPC54_ETH_DMACH_TX_CTRL(0));
lpc54_putreg(regval, LPC54_ETH_DMACH_TX_CTRL(0));
/* Then enable the Rx/Tx */
regval = getreg32(LPC54_ETH_MAC_CONFIG);
regval = lpc54_getreg(LPC54_ETH_MAC_CONFIG);
regval |= ETH_MAC_CONFIG_RE;
putreg32(regval, LPC54_ETH_MAC_CONFIG);
lpc54_putreg(regval, LPC54_ETH_MAC_CONFIG);
regval |= ETH_MAC_CONFIG_TE;
putreg32(regval, LPC54_ETH_MAC_CONFIG);
lpc54_putreg(regval, LPC54_ETH_MAC_CONFIG);
/* Set and activate a timer process */
@ -1948,7 +2061,7 @@ static int lpc54_eth_ifdown(struct net_driver_s *dev)
wd_cancel(priv->eth_txpoll);
wd_cancel(priv->eth_txtimeout);
/* Put the EMAC in its reset, non-operational state. This should be
/* Put the EMAC in its post-reset, non-operational state. This should be
* a known configuration that will guarantee the lpc54_eth_ifup() always
* successfully brings the interface back up.
*
@ -1957,16 +2070,20 @@ static int lpc54_eth_ifdown(struct net_driver_s *dev)
lpc54_reset_eth();
/* Set the CSR clock divider */
lpc54_set_csrdiv();
/* Select MII or RMII mode */
regval = getreg32(LPC54_SYSCON_ETHPHYSEL);
regval = lpc54_getreg(LPC54_SYSCON_ETHPHYSEL);
regval &= ~SYSCON_ETHPHYSEL_MASK;
#ifdef CONFIG_LPC54_ETH_MII
regval |= SYSCON_ETHPHYSEL_MII;
#else
regval |= SYSCON_ETHPHYSEL_RMII;
#endif
putreg32(regval, LPC54_SYSCON_ETHPHYSEL);
lpc54_putreg(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.
@ -2289,15 +2406,15 @@ static void lpc54_txring_initialize(struct lpc54_ethdriver_s *priv,
/* Set the word-aligned Tx descriptor start/tail pointers. */
regval = (uint32_t)txdesc;
putreg32(regval, LPC54_ETH_DMACH_TXDESC_LIST_ADDR(chan));
lpc54_putreg(regval, LPC54_ETH_DMACH_TXDESC_LIST_ADDR(chan));
regval += txring->tr_ndesc * sizeof(struct enet_txdesc_s);
putreg32(regval, LPC54_ETH_DMACH_TXDESC_TAIL_PTR(chan));
lpc54_putreg(regval, LPC54_ETH_DMACH_TXDESC_TAIL_PTR(chan));
/* Set the Tx ring length */
regval = ETH_DMACH_TXDESC_RING_LENGTH(txring->tr_ndesc);
putreg32(regval, LPC54_ETH_DMACH_TXDESC_RING_LENGTH(chan));
lpc54_putreg(regval, LPC54_ETH_DMACH_TXDESC_RING_LENGTH(chan));
/* Inituialize the Tx desriptors . */
@ -2339,22 +2456,22 @@ static void lpc54_rxring_initialize(struct lpc54_ethdriver_s *priv,
/* Set the word-aligned Rx descriptor start/tail pointers. */
regval = (uint32_t)rxdesc;
putreg32(regval, LPC54_ETH_DMACH_RXDESC_LIST_ADDR(chan));
lpc54_putreg(regval, LPC54_ETH_DMACH_RXDESC_LIST_ADDR(chan));
regval += rxring->rr_ndesc * sizeof(struct enet_rxdesc_s);
putreg32(regval, LPC54_ETH_DMACH_RXDESC_TAIL_PTR(chan));
lpc54_putreg(regval, LPC54_ETH_DMACH_RXDESC_TAIL_PTR(chan));
/* Set the Rx ring length */
regval = ETH_DMACH_RXDESC_RING_LENGTH(rxring->rr_ndesc);
putreg32(regval, LPC54_ETH_DMACH_RXDESC_RING_LENGTH(chan));
lpc54_putreg(regval, LPC54_ETH_DMACH_RXDESC_RING_LENGTH(chan));
/* Set the receive buffer size (in words) in the Rx control register */
regval = getreg32(LPC54_ETH_DMACH_RX_CTRL(chan));
regval = lpc54_getreg(LPC54_ETH_DMACH_RX_CTRL(chan));
regval &= ~ETH_DMACH_RX_CTRL_RBSZ_MASK;
regval |= ETH_DMACH_RX_CTRL_RBSZ(LPC54_BUFFER_SIZE >> 2);
putreg32(regval, LPC54_ETH_DMACH_RX_CTRL(chan));
lpc54_putreg(regval, LPC54_ETH_DMACH_RX_CTRL(chan));
/* Initialize the Rx descriptor ring. */
@ -2461,7 +2578,7 @@ static void lpc54_set_csrdiv(void)
uint32_t srcclk = BOARD_MAIN_CLK / 1000000;
uint32_t regval;
regval = getreg32(LPC54_ETH_MAC_MDIO_ADDR);
regval = lpc54_getreg(LPC54_ETH_MAC_MDIO_ADDR);
regval &= ~ETH_MAC_MDIO_ADDR_CR_MASK;
if (srcclk < 35)
@ -2481,7 +2598,7 @@ static void lpc54_set_csrdiv(void)
regval |= ETH_MAC_MDIO_ADDR_CR_DIV62; /* CSR=100-150 MHz; MDC=CSR/62 */
}
putreg32(regval, LPC54_ETH_MAC_MDIO_ADDR);
lpc54_putreg(regval, LPC54_ETH_MAC_MDIO_ADDR);
}
/****************************************************************************
@ -2506,24 +2623,24 @@ static uint16_t lpc54_phy_read(struct lpc54_ethdriver_s *priv,
/* Set the MII read command. */
regval = getreg32(LPC54_ETH_MAC_MDIO_ADDR);
regval = lpc54_getreg(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_ETH_PHYADDR);
putreg32(regval, LPC54_ETH_MAC_MDIO_ADDR);
lpc54_putreg(regval, LPC54_ETH_MAC_MDIO_ADDR);
/* Initiate the read */
regval |= ETH_MAC_MDIO_ADDR_MB;
putreg32(regval, LPC54_ETH_MAC_MDIO_ADDR);
lpc54_putreg(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)
while ((lpc54_getreg(LPC54_ETH_MAC_MDIO_ADDR) & ETH_MAC_MDIO_ADDR_MB) != 0)
{
}
return (uint16_t)getreg32(LPC54_ETH_MAC_MDIO_DATA);
return (uint16_t)lpc54_getreg(LPC54_ETH_MAC_MDIO_DATA);
}
/****************************************************************************
@ -2549,24 +2666,24 @@ static void lpc54_phy_write(struct lpc54_ethdriver_s *priv,
/* Set the MII write command. */
regval = getreg32(LPC54_ETH_MAC_MDIO_ADDR);
regval = lpc54_getreg(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_ETH_PHYADDR);
putreg32(regval, LPC54_ETH_MAC_MDIO_ADDR);
lpc54_putreg(regval, LPC54_ETH_MAC_MDIO_ADDR);
/* Set the write data */
putreg32((uint32_t)phyval, LPC54_ETH_MAC_MDIO_DATA);
lpc54_putreg((uint32_t)phyval, LPC54_ETH_MAC_MDIO_DATA);
/* Initiate the write */
regval |= ETH_MAC_MDIO_ADDR_MB;
putreg32(regval, LPC54_ETH_MAC_MDIO_ADDR);
lpc54_putreg(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)
while ((lpc54_getreg(LPC54_ETH_MAC_MDIO_ADDR) & ETH_MAC_MDIO_ADDR_MB) != 0)
{
}
}
@ -2631,6 +2748,7 @@ static int lpc54_phy_autonegotiate(struct lpc54_ethdriver_s *priv)
{
if (timeout-- <= 0)
{
nerr("ERROR: Autonegotion timed out\n");
return -ETIMEDOUT;
}
@ -2649,6 +2767,7 @@ static int lpc54_phy_autonegotiate(struct lpc54_ethdriver_s *priv)
{
if (timeout-- <= 0)
{
nerr("ERROR: Link status UP timed out\n");
return -ETIMEDOUT;
}
}
@ -2696,6 +2815,7 @@ static int lpc54_phy_reset(struct lpc54_ethdriver_s *priv)
{
if (timeout-- <= 0)
{
nerr("ERROR: PHY start up timed out\n");
return -ETIMEDOUT;
}
@ -2712,6 +2832,7 @@ static int lpc54_phy_reset(struct lpc54_ethdriver_s *priv)
{
if (timeout-- <= 0)
{
nerr("ERROR: PHY reset timed out\n");
return -ETIMEDOUT;
}
@ -2758,28 +2879,31 @@ int up_netinitialize(int intf)
/* Attach the three Ethernet-related IRQs to the handlers */
if (irq_attach(LPC54_IRQ_ETHERNET, lpc54_eth_interrupt, priv))
ret = irq_attach(LPC54_IRQ_ETHERNET, lpc54_eth_interrupt, priv);
if (ret < 0)
{
/* We could not attach the ISR to the interrupt */
nerr("ERROR: irq_attach failed\n");
nerr("ERROR: irq_attach failed: %d\n", ret);
return -EAGAIN;
}
#if 0 /* Not used */
if (irq_attach(LPC54_IRQ_ETHERNETPMT, lpc54_pmt_interrupt, priv))
ret = irq_attach(LPC54_IRQ_ETHERNETPMT, lpc54_pmt_interrupt, priv);
if (ret < 0)
{
/* We could not attach the ISR to the interrupt */
nerr("ERROR: irq_attach for PMTfailed\n");
nerr("ERROR: irq_attach for PMT failed: %d\n", ret);
return -EAGAIN;
}
if (irq_attach(LPC54_IRQ_ETHERNETMACLP, lpc54_mac_interrupt, priv))
ret = irq_attach(LPC54_IRQ_ETHERNETMACLP, lpc54_mac_interrupt, priv);
if (ret < 0)
{
/* We could not attach the ISR to the interrupt */
nerr("ERROR: irq_attach for MAC failed\n");
nerr("ERROR: irq_attach for MAC failed: %d\n", ret);
return -EAGAIN;
}
#endif
@ -2849,10 +2973,6 @@ int up_netinitialize(int intf)
lpc54_eth_enableclk();
/* Set the CSR clock divider */
lpc54_set_csrdiv();
/* Put the interface in the down state. This amounts to resetting the
* device by calling lpc54_eth_ifdown().
*/

View file

@ -258,11 +258,9 @@ struct lpc54_dev_s
#ifdef CONFIG_LPC54_SDMMC_REGDEBUG
static uint32_t lpc54_getreg(uint32_t addr);
static void lpc54_putreg(uint32_t val, uint32_t addr);
static void lpc54_checksetup(void);
#else
# define lpc54_getreg(addr) getreg32(addr)
# define lpc54_putreg(val,addr) putreg32(val,addr)
# define lpc54_checksetup()
#endif
/* Low-level helpers ********************************************************/

View file

@ -393,7 +393,7 @@ void xmc4_clock_configure(void)
/* Setup peripheral clock divider */
putreg32(PBCLKCR_VALUE, XMC4_SCU_PBCLKCR);
putreg32(PBCLKCR_VALUE, XMC4_SCU_PBCLKCR);
/* Setup fCPU clock */

View file

@ -237,6 +237,11 @@ Configurations
3. SDRAM support is enabled and the SDRAM is added to the system heap. The
Ramtest applications is not enabled.
4. This configuration does not include support for aysnchronous network
initialization. As a consequence, NSH must bring up the network
before you get the NSH prompt. If the network cable is unplugged,
this can mean a significant delay before you see the prompt.
nsh:
Configures the NuttShell (nsh) application located at examples/nsh.

View file

@ -22,6 +22,7 @@ CONFIG_INPUT=y
CONFIG_LPC54_EMC_DYNAMIC_CS0_SIZE=0x01000000
CONFIG_LPC54_EMC_DYNAMIC_CS0=y
CONFIG_LPC54_EMC=y
CONFIG_LPC54_ETH_PHYADDR=0
CONFIG_LPC54_ETHERNET=y
CONFIG_LPC54_GPIOIRQ=y
CONFIG_LPC54_USART0=y
@ -47,7 +48,6 @@ CONFIG_NFILE_DESCRIPTORS=8
CONFIG_NFILE_STREAMS=8
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_DISABLE_IFUPDOWN=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_LINELEN=64
CONFIG_NSH_NETLOCAL=y

View file

@ -104,7 +104,7 @@
/* Select the external crystal as the PLL clock source */
# define BOARD_PLL_CLOCKSRC_XTAL 1 /* PLL Clock source == extnernal crystal */
# define BOARD_PLL_CLOCKSRC_XTAL 1 /* PLL Clock source == external crystal */
# undef BOARD_PLL_CLOCKSRC_OFI /* PLL Clock source != internal fast oscillator */
/* PLL Configuration:

View file

@ -351,13 +351,23 @@
#define MII_PHYID1_LAN8720 0x0007 /* ID1 value for LAN8720 */
#define MII_PHYID2_LAN8720 0xc0f1 /* ID2 value for LAN8720 */
/* SMSC LAN8720 SPCR register bits */
/* SMSC LAN8720 SPSCR 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_SCRMDIS (1 << 0) /* Bit 0: Scramble disable */
/* Bit 1: Reserved */
#define MII_LAN8720_SPSCR_MODE_SHIFT (2) /* Bits 2-4: Speed/duplex mode */
#define MII_LAN8720_SPSCR_MODE_MASK (7 << MII_LAN8720_SPSCR_MODE_SHIFT)
# 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: Full duplex mode */
/* Bit 5: Reserved */
#define MII_LAN8720_SPSCR_ENAB4B5B (1 << 6) /* Bit 6: Enable 4B5B */
#define MII_LAN8720_SPSCR_GPIO0 (1 << 7) /* Bit 7: GPIO0 */
#define MII_LAN8720_SPSCR_GPIO1 (1 << 8) /* Bit 8: GPIO1 */
#define MII_LAN8720_SPSCR_GPIO2 (1 << 9) /* Bit 9: GPIO2 */
/* Bit 10-11: Reserved */
#define MII_LAN8720_SPSCR_ANEGDONE (1 << 12) /* Bit 12: Autonegotiation complete */
/* Bits 13-15: Reserved */
/* SMSC LAN8740 MII ID1/2 register bits */

View file

@ -39,6 +39,8 @@
#include <nuttx/config.h>
#include <errno.h>
#include <nuttx/irq.h>
#include "irq/irq.h"
@ -59,7 +61,7 @@
int irq_attach(int irq, xcpt_t isr, FAR void *arg)
{
#if NR_IRQS > 0
int ret = ERROR;
int ret = -EINVAL;
if ((unsigned)irq < NR_IRQS)
{