From 09245e094fe95c92bee0764f31b771b4a07a89c1 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Thu, 29 Jan 2026 21:01:49 +0000 Subject: net: dwc_eth_qos: Use lower_32_bits() for tail pointers The DesignWare Cores Ethernet Quality-of-Service databook state that the descriptor address from the start to the end of the ring must not cross the 4GB boundary. Use lower_32_bits() to write the lower 32 bits of descriptor addresses, including the 32-bit tail pointers, consistently. No functional change is intended. Signed-off-by: Jonas Karlman --- drivers/net/dwc_eth_qos.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 551ee0ea6a0..74cdaa27644 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -683,7 +683,6 @@ static int eqos_start(struct udevice *dev) int ret, i; ulong rate; u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl; - ulong last_rx_desc; ulong desc_pad; ulong addr64; @@ -1019,8 +1018,8 @@ static int eqos_start(struct udevice *dev) * that's not distinguishable from none of the descriptors being * available. */ - last_rx_desc = (ulong)eqos_get_desc(eqos, EQOS_DESCRIPTORS_RX - 1, true); - writel(last_rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); + addr64 = (ulong)eqos_get_desc(eqos, EQOS_DESCRIPTORS_RX - 1, true); + writel(lower_32_bits(addr64), &eqos->dma_regs->ch0_rxdesc_tail_pointer); eqos->started = true; @@ -1116,8 +1115,8 @@ static int eqos_send(struct udevice *dev, void *packet, int length) tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | length; eqos->config->ops->eqos_flush_desc(tx_desc); - writel((ulong)eqos_get_desc(eqos, eqos->tx_desc_idx, false), - &eqos->dma_regs->ch0_txdesc_tail_pointer); + writel(lower_32_bits((ulong)eqos_get_desc(eqos, eqos->tx_desc_idx, false)), + &eqos->dma_regs->ch0_txdesc_tail_pointer); for (i = 0; i < 1000000; i++) { eqos->config->ops->eqos_inval_desc(tx_desc); @@ -1198,7 +1197,8 @@ static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_BUF1V; eqos->config->ops->eqos_flush_desc(rx_desc); } - writel((ulong)rx_desc, &eqos->dma_regs->ch0_rxdesc_tail_pointer); + writel(lower_32_bits((ulong)rx_desc), + &eqos->dma_regs->ch0_rxdesc_tail_pointer); } eqos->rx_desc_idx++; -- cgit v1.3.1 From 34c1ab534c69366d6eeb3d693a9afd37bd14aba5 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Thu, 29 Jan 2026 21:01:50 +0000 Subject: net: dwc_eth_qos: Initialize the transmit tail pointer in eqos_start() The DesignWare Cores Ethernet Quality-of-Service databook state that descriptors up to one location less than the one indicated by the descriptor tail pointer are owned by the DMA. The DMA continues to process the descriptors until the following condition occurs: Current Descriptor Pointer == Descriptor Tail Pointer The DMA goes into suspend mode when this condition occurs, and updating the tail pointer resume the DMA processing. Configure the transmit tail pointer to the first (current) descriptor pointer so that the tail pointer is a valid address instead of being initialized to NULL when transmit DMA is started. Also update the receive tail pointer comment to state that by pointing to the last descriptor we are actually implying that all receive descriptors are owned by and can be processed by the DMA. Signed-off-by: Jonas Karlman --- drivers/net/dwc_eth_qos.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 74cdaa27644..08332210afb 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1011,12 +1011,17 @@ static int eqos_start(struct udevice *dev) setbits_le32(&eqos->mac_regs->configuration, EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); - /* TX tail pointer not written until we need to TX a packet */ /* - * Point RX tail pointer at last descriptor. Ideally, we'd point at the - * first descriptor, implying all descriptors were available. However, - * that's not distinguishable from none of the descriptors being - * available. + * Point TX tail pointer at the first descriptor, implying no descriptor + * are owned by the DMA. We advance the tail pointer when we need to TX + * a packet in eqos_send(). + */ + addr64 = (ulong)eqos_get_desc(eqos, 0, false); + writel(lower_32_bits(addr64), &eqos->dma_regs->ch0_txdesc_tail_pointer); + + /* + * Point RX tail pointer at the last descriptor, implying all + * descriptors are owned by the DMA. */ addr64 = (ulong)eqos_get_desc(eqos, EQOS_DESCRIPTORS_RX - 1, true); writel(lower_32_bits(addr64), &eqos->dma_regs->ch0_rxdesc_tail_pointer); -- cgit v1.3.1 From 8beb70f2309d6fd6abb1d5c539edab9b0934d656 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Thu, 29 Jan 2026 21:01:51 +0000 Subject: net: dwc_eth_qos: Start DMA and MAC after tail pointers are initialized The DesignWare Cores Ethernet Quality-of-Service databook state that receive and transmit descriptor list address and also transmit and receive tail pointer registers should be initialized before the receive and transmit DMAs are started. It also state to enable the MAC receiver only after the DMA is active. Otherwise, received frames can fill the Rx FIFO and overflow. Move the activation of receive and transmit DMA and MAC receiver until after tail pointer registers have been initialized. Signed-off-by: Jonas Karlman --- drivers/net/dwc_eth_qos.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 08332210afb..b104d4e4725 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1003,14 +1003,6 @@ static int eqos_start(struct udevice *dev) writel(EQOS_DESCRIPTORS_RX - 1, &eqos->dma_regs->ch0_rxdesc_ring_length); - /* Enable everything */ - setbits_le32(&eqos->dma_regs->ch0_tx_control, - EQOS_DMA_CH0_TX_CONTROL_ST); - setbits_le32(&eqos->dma_regs->ch0_rx_control, - EQOS_DMA_CH0_RX_CONTROL_SR); - setbits_le32(&eqos->mac_regs->configuration, - EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); - /* * Point TX tail pointer at the first descriptor, implying no descriptor * are owned by the DMA. We advance the tail pointer when we need to TX @@ -1026,6 +1018,14 @@ static int eqos_start(struct udevice *dev) addr64 = (ulong)eqos_get_desc(eqos, EQOS_DESCRIPTORS_RX - 1, true); writel(lower_32_bits(addr64), &eqos->dma_regs->ch0_rxdesc_tail_pointer); + /* Enable everything */ + setbits_le32(&eqos->dma_regs->ch0_tx_control, + EQOS_DMA_CH0_TX_CONTROL_ST); + setbits_le32(&eqos->dma_regs->ch0_rx_control, + EQOS_DMA_CH0_RX_CONTROL_SR); + setbits_le32(&eqos->mac_regs->configuration, + EQOS_MAC_CONFIGURATION_TE | EQOS_MAC_CONFIGURATION_RE); + eqos->started = true; debug("%s: OK\n", __func__); -- cgit v1.3.1 From 5fdc297b893eb5cc3e0cfe43359fba9680aa0299 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Thu, 29 Jan 2026 21:01:52 +0000 Subject: net: dwc_eth_qos: Define more of the unused MAC regs Multicast and Broadcast Queue Enable and Promiscuous Mode Enable bits are currently written to "unused" registers using magic values. Define more of the "unused" MAC regs based on information in the DesignWare Cores Ethernet Quality-of-Service databook. Signed-off-by: Jonas Karlman --- drivers/net/dwc_eth_qos.c | 10 +++++----- drivers/net/dwc_eth_qos.h | 28 ++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index b104d4e4725..8a396d0b29e 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -890,11 +890,11 @@ static int eqos_start(struct udevice *dev) EQOS_MAC_RXQ_CTRL0_RXQ0EN_SHIFT); /* Multicast and Broadcast Queue Enable */ - setbits_le32(&eqos->mac_regs->unused_0a4, - 0x00100000); - /* enable promise mode */ - setbits_le32(&eqos->mac_regs->unused_004[1], - 0x1); + setbits_le32(&eqos->mac_regs->rxq_ctrl1, + EQOS_MAC_RXQ_CTRL1_MCBCQEN); + /* Promiscuous Mode Enable */ + setbits_le32(&eqos->mac_regs->packet_filter, + EQOS_MAC_PACKET_FILTER_PR); /* Set TX flow control parameters */ /* Set Pause Time */ diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h index c239a5c7aca..ba16f1a37cb 100644 --- a/drivers/net/dwc_eth_qos.h +++ b/drivers/net/dwc_eth_qos.h @@ -14,23 +14,31 @@ #define EQOS_MAC_REGS_BASE 0x000 struct eqos_mac_regs { u32 configuration; /* 0x000 */ - u32 unused_004[(0x070 - 0x004) / 4]; /* 0x004 */ + u32 ext_configuration; /* 0x004 */ + u32 packet_filter; /* 0x008 */ + u32 watchdog_timeout; /* 0x00c */ + u32 unused_010[(0x070 - 0x010) / 4]; /* 0x010 */ u32 q0_tx_flow_ctrl; /* 0x070 */ - u32 unused_070[(0x090 - 0x074) / 4]; /* 0x074 */ + u32 unused_074[(0x090 - 0x074) / 4]; /* 0x074 */ u32 rx_flow_ctrl; /* 0x090 */ - u32 unused_094; /* 0x094 */ + u32 rxq_ctrl4; /* 0x094 */ u32 txq_prty_map0; /* 0x098 */ - u32 unused_09c; /* 0x09c */ + u32 txq_prty_map1; /* 0x09c */ u32 rxq_ctrl0; /* 0x0a0 */ - u32 unused_0a4; /* 0x0a4 */ + u32 rxq_ctrl1; /* 0x0a4 */ u32 rxq_ctrl2; /* 0x0a8 */ - u32 unused_0ac[(0x0dc - 0x0ac) / 4]; /* 0x0ac */ + u32 rxq_ctrl3; /* 0x0ac */ + u32 unused_0b0[(0x0dc - 0x0b0) / 4]; /* 0x0b0 */ u32 us_tic_counter; /* 0x0dc */ - u32 unused_0e0[(0x11c - 0x0e0) / 4]; /* 0x0e0 */ + u32 unused_0e0[(0x110 - 0x0e0) / 4]; /* 0x0e0 */ + u32 version; /* 0x110 */ + u32 debug; /* 0x114 */ + u32 unused_118; /* 0x118 */ u32 hw_feature0; /* 0x11c */ u32 hw_feature1; /* 0x120 */ u32 hw_feature2; /* 0x124 */ - u32 unused_128[(0x200 - 0x128) / 4]; /* 0x128 */ + u32 hw_feature3; /* 0x128 */ + u32 unused_12c[(0x200 - 0x12c) / 4]; /* 0x12c */ u32 mdio_address; /* 0x200 */ u32 mdio_data; /* 0x204 */ u32 unused_208[(0x300 - 0x208) / 4]; /* 0x208 */ @@ -51,6 +59,8 @@ struct eqos_mac_regs { #define EQOS_MAC_CONFIGURATION_TE BIT(1) #define EQOS_MAC_CONFIGURATION_RE BIT(0) +#define EQOS_MAC_PACKET_FILTER_PR BIT(0) + #define EQOS_MAC_Q0_TX_FLOW_CTRL_PT_SHIFT 16 #define EQOS_MAC_Q0_TX_FLOW_CTRL_PT_MASK 0xffff #define EQOS_MAC_Q0_TX_FLOW_CTRL_TFE BIT(1) @@ -66,6 +76,8 @@ struct eqos_mac_regs { #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB 2 #define EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV 1 +#define EQOS_MAC_RXQ_CTRL1_MCBCQEN BIT(20) + #define EQOS_MAC_RXQ_CTRL2_PSRQ0_SHIFT 0 #define EQOS_MAC_RXQ_CTRL2_PSRQ0_MASK 0xff -- cgit v1.3.1 From 1db453a5fee45194be920de6d1b5edf2117ebe1c Mon Sep 17 00:00:00 2001 From: Mikhail Kshevetskiy Date: Sat, 31 Jan 2026 01:06:23 +0300 Subject: net: airoha_eth: fix mdio binding to switch device Commit d2145a89bcf6 ("net: airoha: bind MDIO controller on Ethernet load") refers to non-present CONFIG_MDIO_MT7531 and non-present "mt7531-mdio" driver. It should use CONFIG_MDIO_MT7531_MMIO and "mt7531-mdio-mmio" instead. Fixes: d2145a89bcf6 ("net: airoha: bind MDIO controller on Ethernet load") Signed-off-by: Mikhail Kshevetskiy --- drivers/net/Kconfig | 2 +- drivers/net/airoha_eth.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 4fda1b0c28c..47e2fa192c2 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -127,7 +127,7 @@ config AIROHA_ETH select PHYLIB select DEVRES select DM_RESET - select MDIO_MT7531 + select MDIO_MT7531_MMIO help This Driver support Airoha Ethernet QDMA Driver Say Y to enable support for the Airoha Ethernet QDMA. diff --git a/drivers/net/airoha_eth.c b/drivers/net/airoha_eth.c index 046b677d78e..5e393db5ffe 100644 --- a/drivers/net/airoha_eth.c +++ b/drivers/net/airoha_eth.c @@ -989,7 +989,7 @@ static int airoha_eth_bind(struct udevice *dev) struct udevice *mdio_dev; int ret = 0; - if (!CONFIG_IS_ENABLED(MDIO_MT7531)) + if (!CONFIG_IS_ENABLED(MDIO_MT7531_MMIO)) return 0; switch_node = ofnode_by_compatible(ofnode_null(), @@ -1005,7 +1005,7 @@ static int airoha_eth_bind(struct udevice *dev) return 0; } - ret = device_bind_driver_to_node(dev, "mt7531-mdio", "mdio", + ret = device_bind_driver_to_node(dev, "mt7531-mdio-mmio", "mdio", mdio_node, &mdio_dev); if (ret) debug("Warning: failed to bind mdio controller\n"); -- cgit v1.3.1 From caa62920e32a4ea2c134b44265eb19429814b430 Mon Sep 17 00:00:00 2001 From: Mikhail Kshevetskiy Date: Sat, 31 Jan 2026 01:06:24 +0300 Subject: net: airoha_eth: use proper switch node for en7523 case Commit d2145a89bcf6 ("net: airoha: bind MDIO controller on Ethernet load") uses "airoha,en7581-switch" dts node for finding MDIO childs. This is wrong for EN7523 SoC. The correct node name should be used instead. Fixes: d2145a89bcf6 ("net: airoha: bind MDIO controller on Ethernet load") Signed-off-by: Mikhail Kshevetskiy --- drivers/net/airoha_eth.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/airoha_eth.c b/drivers/net/airoha_eth.c index 5e393db5ffe..3a0ac7ce368 100644 --- a/drivers/net/airoha_eth.c +++ b/drivers/net/airoha_eth.c @@ -985,6 +985,7 @@ static int arht_eth_write_hwaddr(struct udevice *dev) static int airoha_eth_bind(struct udevice *dev) { + struct airoha_eth_soc_data *data = (void *)dev_get_driver_data(dev); ofnode switch_node, mdio_node; struct udevice *mdio_dev; int ret = 0; @@ -993,7 +994,7 @@ static int airoha_eth_bind(struct udevice *dev) return 0; switch_node = ofnode_by_compatible(ofnode_null(), - "airoha,en7581-switch"); + data->switch_compatible); if (!ofnode_valid(switch_node)) { debug("Warning: missing switch node\n"); return 0; -- cgit v1.3.1 From 3aabc0dae03b824ffae06a16a48bf2c89b5c36e7 Mon Sep 17 00:00:00 2001 From: Mikhail Kshevetskiy Date: Sat, 31 Jan 2026 01:06:25 +0300 Subject: net: mdio-mt7531-mmio: fix switch regs initialization mdio is a child node of the switch, so to get switch base address we need to lookup for a parent node Signed-off-by: Mikhail Kshevetskiy --- drivers/net/mdio-mt7531-mmio.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mdio-mt7531-mmio.c b/drivers/net/mdio-mt7531-mmio.c index 3e325ca58da..5a0725010f2 100644 --- a/drivers/net/mdio-mt7531-mmio.c +++ b/drivers/net/mdio-mt7531-mmio.c @@ -151,8 +151,13 @@ static const struct mdio_ops mt7531_mdio_ops = { static int mt7531_mdio_probe(struct udevice *dev) { struct mt7531_mdio_priv *priv = dev_get_priv(dev); + ofnode switch_node; - priv->switch_regs = dev_read_addr(dev); + switch_node = ofnode_get_parent(dev_ofnode(dev)); + if (!ofnode_valid(switch_node)) + return -EINVAL; + + priv->switch_regs = ofnode_get_addr(switch_node); if (priv->switch_regs == FDT_ADDR_T_NONE) return -EINVAL; -- cgit v1.3.1 From e7b83e64d6bc9f2366669118cb596d75f811eb89 Mon Sep 17 00:00:00 2001 From: Charles Perry Date: Tue, 3 Feb 2026 11:01:40 -0800 Subject: net: phy: mscc: allow RGMII with internal delay for the VSC8541 Add the missing RGMII modes with internal delay for the VSC8541. Fixes: a5fd13ad1913 ("net: phy: MSCC Add Support for VSC8530-VSC8531-VSC8540-VSC8541") Signed-off-by: Charles Perry --- drivers/net/phy/mscc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c index bd9cd952975..7263887b9ce 100644 --- a/drivers/net/phy/mscc.c +++ b/drivers/net/phy/mscc.c @@ -1371,6 +1371,9 @@ static int vsc8541_config(struct phy_device *phydev) case PHY_INTERFACE_MODE_GMII: case PHY_INTERFACE_MODE_RMII: case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_TXID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: retval = vsc8531_vsc8541_mac_config(phydev); if (retval != 0) return retval; -- cgit v1.3.1