Skip to content

arch/risc-v/mpfs ethernet improvements #15979

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions arch/risc-v/src/mpfs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,14 @@ config MPFS_PHYINIT
---help---
call mpfs_phy_boardinitialize() on init

config MPFS_PHY_RX_TIMEOUT_WA
int "RX restart timeout workaround"
default 0
---help---
This is a workaround for LAN8742A rev A and B silicon errata.
Reset ETH interface in case no RX packets have been received
in configured time. Set to 0 to disable.

config MPFS_ETH0_PHY_KSZ9477
bool "Use ksz9477 switch as an SGMII PHY for ETH0"
default n
Expand Down Expand Up @@ -767,6 +775,13 @@ endchoice # GMAC speed

endif # !MPFS_MAC_AUTONEG

config MPFS_ETHMAC_HPWORK
bool "Use HP workqueue"
default n
depends on MPFS_ETHMAC
---help---
Select HPWORK workqueue for eth ISR work

config MPFS_ETHMAC_MDC_CLOCK_SOURCE_HZ
int "MDC Clock Source (Hz)"
default 125000000
Expand Down
94 changes: 62 additions & 32 deletions arch/risc-v/src/mpfs/mpfs_ethernet.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
#include "hardware/mpfs_ethernet.h"
#include "hardware/mpfs_mpucfg.h"

#define SIZE_ALIGNED_64(m) (((m) + (0x3f)) & ~0x3f)

#if defined(CONFIG_MPFS_ETH0_PHY_KSZ9477) ||\
defined(CONFIG_MPFS_ETH1_PHY_KSZ9477)
# if !defined(CONFIG_MPFS_MAC_SGMII)
Expand Down Expand Up @@ -100,8 +102,6 @@

# if defined(CONFIG_MPFS_ETHMAC_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_MPFS_ETHMAC_LPWORK)
# define ETHWORK LPWORK
# else
# define ETHWORK LPWORK
# endif
Expand Down Expand Up @@ -131,21 +131,18 @@
# define CONFIG_MPFS_ETHMAC_NTXBUFFERS (8)
#endif

/* GMAC buffer sizes
* REVISIT: do we want to make GMAC_RX_UNITSIZE configurable?
* issue when using the MTU size receive block
*/

#define GMAC_RX_UNITSIZE (512) /* Fixed size for RX buffer */
#define GMAC_TX_UNITSIZE CONFIG_NET_ETH_PKTSIZE /* MAX size for Ethernet packet */

/* The MAC can support frame lengths up to 1536 bytes */

#define GMAC_MAX_FRAMELEN (1536)
#if CONFIG_NET_ETH_PKTSIZE > GMAC_MAX_FRAMELEN
# error CONFIG_NET_ETH_PKTSIZE is too large
#endif

/* Max size of RX and TX buffers */

#define GMAC_RX_UNITSIZE SIZE_ALIGNED_64(GMAC_MAX_FRAMELEN)
#define GMAC_TX_UNITSIZE SIZE_ALIGNED_64(CONFIG_NET_ETH_PKTSIZE)

/* for DMA dma_rxbuf_size */

#define MPFS_MAC_RX_BUF_VALUE ((GMAC_RX_UNITSIZE + 63) / 64)
Expand Down Expand Up @@ -173,6 +170,15 @@

#define MPFS_TXTIMEOUT (60 * CLK_TCK)

/* RX timeout: Workaround for LAN8742A rev A and B silicon errata
* "Cable diagnostics incorrectly returns Open cable connection for
* terminated cable"
*/

#if CONFIG_MPFS_PHY_RX_TIMEOUT_WA != 0
#define MPFS_RXTIMEOUT (CONFIG_MPFS_PHY_RX_TIMEOUT_WA * CLK_TCK)
#endif

/* PHY reset tim in loop counts */

#define PHY_RESET_WAIT_COUNT (10)
Expand Down Expand Up @@ -270,8 +276,12 @@ struct mpfs_ethmac_s
uint8_t phyaddr; /* PHY address */
#endif
struct wdog_s txtimeout; /* TX timeout timer */
#ifdef MPFS_RXTIMEOUT
struct wdog_s rxtimeout; /* RX timeout timer */
#endif
struct work_s irqwork; /* For deferring interrupt work to the work queue */
struct work_s pollwork; /* For deferring poll work to the work queue */
struct work_s timeoutwork; /* For managing timeouts */

/* This holds the information visible to the NuttX network */

Expand Down Expand Up @@ -391,6 +401,7 @@ static int mpfs_ethconfig(struct mpfs_ethmac_s *priv);
static void mpfs_ethreset(struct mpfs_ethmac_s *priv);

static void mpfs_interrupt_work(void *arg);
static void mpfs_txtimeout_expiry(wdparm_t arg);

/****************************************************************************
* Private Functions
Expand Down Expand Up @@ -472,6 +483,16 @@ static int mpfs_interrupt_0(int irq, void *context, void *arg)
wd_cancel(&priv->txtimeout);
}

#ifdef MPFS_RXTIMEOUT
if ((isr & INT_RX) != 0)
{
/* If a RX transfer just completed, restart the timeout */

wd_start(&priv->rxtimeout, MPFS_RXTIMEOUT,
mpfs_txtimeout_expiry, (wdparm_t)priv);
}
#endif

/* Schedule to perform the interrupt processing on the worker thread. */

work_queue(ETHWORK, &priv->irqwork, mpfs_interrupt_work, priv, 0);
Expand Down Expand Up @@ -1560,6 +1581,15 @@ static int mpfs_ifup(struct net_driver_s *dev)
up_enable_irq(priv->mac_q_int[2]);
up_enable_irq(priv->mac_q_int[3]);

#ifdef MPFS_RXTIMEOUT
/* Set up the RX timeout. If we don't receive anything in time, try
* to re-initialize
*/

wd_start(&priv->rxtimeout, MPFS_RXTIMEOUT,
mpfs_txtimeout_expiry, (wdparm_t)priv);
#endif

return OK;
}

Expand Down Expand Up @@ -1603,6 +1633,12 @@ static int mpfs_ifdown(struct net_driver_s *dev)

wd_cancel(&priv->txtimeout);

#ifdef MPFS_RXTIMEOUT
/* Cancel the RX timeout timers */

wd_cancel(&priv->rxtimeout);
#endif

/* Put the MAC in its reset, non-operational state. This should be
* a known configuration that will guarantee the mpfs_ifup() always
* successfully brings the interface back up.
Expand Down Expand Up @@ -2209,7 +2245,8 @@ static int mpfs_phyfind(struct mpfs_ethmac_s *priv, uint8_t *phyaddr)
*
****************************************************************************/

#if defined(CONFIG_DEBUG_NET) && defined(CONFIG_DEBUG_INFO)
#if defined(CONFIG_DEBUG_NET) && defined(CONFIG_DEBUG_INFO) && \
defined(ETH_HAS_MDIO_PHY)
static void mpfs_phydump(struct mpfs_ethmac_s *priv)
{
uint16_t phyval;
Expand Down Expand Up @@ -2564,6 +2601,8 @@ static void mpfs_linkspeed(struct mpfs_ethmac_s *priv)

mac_putreg(priv, NETWORK_CONFIG, regval);
mac_putreg(priv, NETWORK_CONTROL, ncr);

mpfs_phydump(priv);
}
#endif

Expand Down Expand Up @@ -2888,7 +2927,7 @@ static void mpfs_txtimeout_expiry(wdparm_t arg)

/* Schedule to perform the TX timeout processing on the worker thread. */

work_queue(ETHWORK, &priv->irqwork, mpfs_txtimeout_work, priv, 0);
work_queue(LPWORK, &priv->timeoutwork, mpfs_txtimeout_work, priv, 0);
}

/****************************************************************************
Expand Down Expand Up @@ -3328,6 +3367,17 @@ static int mpfs_phyinit(struct mpfs_ethmac_s *priv)
{
int ret = -EINVAL;

#ifdef CONFIG_MPFS_PHYINIT
/* Perform any necessary, board-specific PHY initialization */

ret = mpfs_phy_boardinitialize(priv->intf);
if (ret < 0)
{
nerr("ERROR: Failed to initialize the PHY: %d\n", ret);
return ret;
}
#endif

#ifdef ETH_HAS_MDIO_PHY

/* Configure PHY clocking */
Expand Down Expand Up @@ -3478,31 +3528,11 @@ static int mpfs_ethconfig(struct mpfs_ethmac_s *priv)

ninfo("Entry\n");

#ifdef CONFIG_MPFS_PHYINIT
/* Perform any necessary, board-specific PHY initialization */

ret = mpfs_phy_boardinitialize(priv->intf);
if (ret < 0)
{
nerr("ERROR: Failed to initialize the PHY: %d\n", ret);
return ret;
}
#endif

/* Reset the Ethernet block */

ninfo("Reset the Ethernet block\n");
mpfs_ethreset(priv);

/* Initialize the PHY */

ninfo("Initialize the PHY\n");
ret = mpfs_phyinit(priv);
if (ret < 0)
{
return ret;
}

/* Initialize the MAC and DMA */

ninfo("Initialize the MAC and DMA\n");
Expand Down
Loading