mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v2 0/4] net: expand gianfar support to ls1021a
@ 2026-02-04 11:46 Renaud Barbier
  2026-02-04 11:46 ` [PATCH v2 1/4] net: gianfar: disable link information Renaud Barbier
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Renaud Barbier @ 2026-02-04 11:46 UTC (permalink / raw)
  To: barebox; +Cc: Renaud Barbier

This patch adds limited support for the Ethernet controller on the NXP
LS1021A:
    * Only one port has been tested i.e enet1.
    * The PHY negotiation has been limited to 100Mbits-FD.

The version 2 splits some cosmetics change in the code from the actual
Ethernet controller support.

Renaud Barbier (4):
  net: gianfar: disable link information
  gianfar: apply checkpatch recommendations
  net:gianfar: add device tree support
  ARM: ls1021a: initial Ethernet and mdio configuration

 arch/arm/boards/ls1021aiot/board.c       |  35 +++
 arch/arm/configs/layerscape_v7_defconfig |   7 +
 arch/arm/dts/fsl-ls1021a-iot.dts         |  28 ++
 arch/powerpc/include/asm/dma.h           |  34 +++
 drivers/net/Kconfig                      |   2 +-
 drivers/net/gianfar.c                    | 326 ++++++++++++++++++-----
 drivers/net/gianfar.h                    |  40 ++-
 7 files changed, 402 insertions(+), 70 deletions(-)

-- 
2.43.0




^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/4] net: gianfar: disable link information
  2026-02-04 11:46 [PATCH v2 0/4] net: expand gianfar support to ls1021a Renaud Barbier
@ 2026-02-04 11:46 ` Renaud Barbier
  2026-02-04 11:46 ` [PATCH v2 2/4] gianfar: apply checkpatch recommendations Renaud Barbier
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Renaud Barbier @ 2026-02-04 11:46 UTC (permalink / raw)
  To: barebox; +Cc: Renaud Barbier

Link information are provided by the PHY layer so turn the information
messages into debug messages.

Signed-off-by: Renaud Barbier <renaud.barbier@ametek.com>
---
 drivers/net/gianfar.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 18b3c8849c..d0f606279f 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -121,11 +121,11 @@ static void gfar_adjust_link(struct eth_device *edev)
 		out_be32(regs + GFAR_ECNTRL_OFFSET, ecntrl);
 		out_be32(regs + GFAR_MACCFG2_OFFSET, maccfg2);
 
-		dev_info(&edev->dev, "Speed: %d, %s duplex\n", priv->speed,
-		       (priv->duplexity) ? "full" : "half");
+		dev_dbg(&edev->dev, "Speed: %d, %s duplex\n", priv->speed,
+				(priv->duplexity) ? "full" : "half");
 
 	} else {
-		dev_info(&edev->dev, "No link.\n");
+		dev_dbg(&edev->dev, "No link.\n");
 	}
 }
 
-- 
2.43.0




^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 2/4] gianfar: apply checkpatch recommendations
  2026-02-04 11:46 [PATCH v2 0/4] net: expand gianfar support to ls1021a Renaud Barbier
  2026-02-04 11:46 ` [PATCH v2 1/4] net: gianfar: disable link information Renaud Barbier
@ 2026-02-04 11:46 ` Renaud Barbier
  2026-02-04 11:46 ` [PATCH v2 3/4] net:gianfar: add device tree support Renaud Barbier
  2026-02-04 11:46 ` [PATCH v2 4/4] ARM: ls1021a: initial Ethernet and mdio configuration Renaud Barbier
  3 siblings, 0 replies; 7+ messages in thread
From: Renaud Barbier @ 2026-02-04 11:46 UTC (permalink / raw)
  To: barebox; +Cc: Renaud Barbier

Replace camel case variables, null pointer tests and fix missing space
and logic.

Signed-off-by: Renaud Barbier <renaud.barbier@ametek.com>
---
 drivers/net/gianfar.c | 19 +++++++++----------
 drivers/net/gianfar.h |  4 ++--
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index d0f606279f..a6eb3bfa01 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -16,7 +16,7 @@
 #include <driver.h>
 #include <command.h>
 #include <errno.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/phy.h>
 #include <linux/err.h>
 #include "gianfar.h"
@@ -77,11 +77,11 @@ static void gfar_adjust_link(struct eth_device *edev)
 	u32 ecntrl, maccfg2;
 
 	priv->link = edev->phydev->link;
-	priv->duplexity =edev->phydev->duplex;
+	priv->duplexity = edev->phydev->duplex;
 
 	if (edev->phydev->speed == SPEED_1000)
 		priv->speed = 1000;
-	if (edev->phydev->speed == SPEED_100)
+	else if (edev->phydev->speed == SPEED_100)
 		priv->speed = 100;
 	else
 		priv->speed = 10;
@@ -194,7 +194,7 @@ static int gfar_open(struct eth_device *edev)
 	for (ix = 0; ix < RX_BUF_CNT; ix++) {
 		out_be16(&priv->rxbd[ix].status, RXBD_EMPTY);
 		out_be16(&priv->rxbd[ix].length, 0);
-		out_be32(&priv->rxbd[ix].bufPtr, (uint) priv->rx_buffer[ix]);
+		out_be32(&priv->rxbd[ix].buf, (uint)priv->rx_buffer[ix]);
 	}
 	out_be16(&priv->rxbd[RX_BUF_CNT - 1].status, RXBD_EMPTY | RXBD_WRAP);
 
@@ -202,7 +202,7 @@ static int gfar_open(struct eth_device *edev)
 	for (ix = 0; ix < TX_BUF_CNT; ix++) {
 		out_be16(&priv->txbd[ix].status, 0);
 		out_be16(&priv->txbd[ix].length, 0);
-		out_be32(&priv->txbd[ix].bufPtr, 0);
+		out_be32(&priv->txbd[ix].buf, 0);
 	}
 	out_be16(&priv->txbd[TX_BUF_CNT - 1].status, TXBD_WRAP);
 
@@ -356,7 +356,7 @@ static int gfar_send(struct eth_device *edev, void *packet, int length)
 	uint16_t status;
 
 	tidx = priv->txidx;
-	out_be32(&priv->txbd[tidx].bufPtr, (u32) packet);
+	out_be32(&priv->txbd[tidx].buf, (u32)packet);
 	out_be16(&priv->txbd[tidx].length, length);
 	out_be16(&priv->txbd[tidx].status,
 		in_be16(&priv->txbd[tidx].status) |
@@ -368,9 +368,8 @@ static int gfar_send(struct eth_device *edev, void *packet, int length)
 	/* Wait for buffer to be transmitted */
 	start = get_time_ns();
 	while (in_be16(&priv->txbd[tidx].status) & TXBD_READY) {
-		if (is_timeout(start, 5 * MSECOND)) {
+		if (is_timeout(start, 5 * MSECOND))
 			break;
-		}
 	}
 
 	status = in_be16(&priv->txbd[tidx].status);
@@ -483,7 +482,7 @@ static int gfar_probe(struct device *dev)
 	priv->tbiana = gfar_info->tbiana;
 
 	mdev = get_device_by_name("gfar-mdio0");
-	if (mdev == NULL) {
+	if (!mdev) {
 		pr_err("gfar-mdio0 was not found\n");
 		return -ENODEV;
 	}
@@ -492,7 +491,7 @@ static int gfar_probe(struct device *dev)
 	if (priv->mdiobus_tbi != 0) {
 		sprintf(devname, "%s%d", "gfar-tbiphy", priv->mdiobus_tbi);
 		mdev = get_device_by_name(devname);
-		if (mdev == NULL) {
+		if (!mdev) {
 			pr_err("%s was not found\n", devname);
 			return -ENODEV;
 		}
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 8ccbbe1473..acb50b9ce3 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -187,13 +187,13 @@
 struct txbd8 {
 	uint16_t     status;	     /* Status Fields */
 	uint16_t     length;	     /* Buffer length */
-	uint32_t     bufPtr;	     /* Buffer Pointer */
+	uint32_t     buf;	     /* Buffer Pointer */
 };
 
 struct rxbd8 {
 	uint16_t     status;	     /* Status Fields */
 	uint16_t     length;	     /* Buffer Length */
-	uint32_t     bufPtr;	     /* Buffer Pointer */
+	uint32_t     buf;	     /* Buffer Pointer */
 };
 
 /* eTSEC general control and status registers */
-- 
2.43.0




^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 3/4] net:gianfar: add device tree support
  2026-02-04 11:46 [PATCH v2 0/4] net: expand gianfar support to ls1021a Renaud Barbier
  2026-02-04 11:46 ` [PATCH v2 1/4] net: gianfar: disable link information Renaud Barbier
  2026-02-04 11:46 ` [PATCH v2 2/4] gianfar: apply checkpatch recommendations Renaud Barbier
@ 2026-02-04 11:46 ` Renaud Barbier
  2026-02-04 11:46 ` [PATCH v2 4/4] ARM: ls1021a: initial Ethernet and mdio configuration Renaud Barbier
  3 siblings, 0 replies; 7+ messages in thread
From: Renaud Barbier @ 2026-02-04 11:46 UTC (permalink / raw)
  To: barebox; +Cc: Renaud Barbier

Like the PPC platforms, the NXP LS1021A Ethernet controller is managed
by the gianfar driver. Since the LS1021A configuration uses a device tree,
add probing through the device tree to the gianfar driver while preserving
the tree-less PPC support.

Signed-off-by: Renaud Barbier <renaud.barbier@ametek.com>
---
 arch/powerpc/include/asm/dma.h |  34 ++++
 drivers/net/Kconfig            |   2 +-
 drivers/net/gianfar.c          | 305 +++++++++++++++++++++++++++------
 drivers/net/gianfar.h          |  36 ++++
 4 files changed, 320 insertions(+), 57 deletions(-)

diff --git a/arch/powerpc/include/asm/dma.h b/arch/powerpc/include/asm/dma.h
index 27d269f491..cfdb8f3cf2 100644
--- a/arch/powerpc/include/asm/dma.h
+++ b/arch/powerpc/include/asm/dma.h
@@ -9,5 +9,39 @@
 #define __ASM_DMA_H
 
 /* empty */
+#include <io.h>
+
+#define arch_sync_dma_for_cpu arch_sync_dma_for_cpu
+static inline void arch_sync_dma_for_cpu(void *vaddr, size_t size,
+					 enum dma_data_direction dir)
+{
+}
+
+#define arch_sync_dma_for_device arch_sync_dma_for_device
+static inline void arch_sync_dma_for_device(void *vaddr, size_t size,
+					    enum dma_data_direction dir)
+{
+}
+
+static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t address,
+					   size_t size, enum dma_data_direction dir)
+{
+}
+
+static inline void dma_sync_single_for_device(struct device *dev, dma_addr_t address,
+					      size_t size, enum dma_data_direction dir)
+{
+}
+
+static inline dma_addr_t dma_map_single(struct device *dev, void *ptr,
+					size_t size, enum dma_data_direction dir)
+{
+	return virt_to_phys(ptr);
+}
+
+static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
+				    size_t size, enum dma_data_direction dir)
+{
+}
 
 #endif /* __ASM_DMA_H */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 068906078c..bd18416d3d 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -237,7 +237,7 @@ config DRIVER_NET_FSL_FMAN
 
 config DRIVER_NET_GIANFAR
 	bool "Gianfar Ethernet"
-	depends on ARCH_MPC85XX
+	depends on ARCH_MPC85XX || ARCH_LS1021
 	select PHYLIB
 
 config DRIVER_NET_KS8851_MLL
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index a6eb3bfa01..0d0993756a 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -8,14 +8,18 @@
  * based on work by Andy Fleming
  */
 
+#ifdef CONFIG_PPC
 #include <asm/config.h>
+#endif
 #include <common.h>
 #include <malloc.h>
 #include <net.h>
+#include <dma.h>
 #include <init.h>
 #include <driver.h>
 #include <command.h>
 #include <errno.h>
+#include <of_address.h>
 #include <linux/io.h>
 #include <linux/phy.h>
 #include <linux/err.h>
@@ -173,28 +177,44 @@ static int gfar_init(struct eth_device *edev)
 	return  0;
 }
 
+static int gfar_receive_packets_setup(struct gfar_private *priv, int ix)
+{
+	dma_addr_t dma;
+
+	dma = dma_map_single(priv->dev, priv->rx_buffer[ix], PKTSIZE,
+				DMA_FROM_DEVICE);
+	if (dma_mapping_error(priv->dev, dma))
+		return -EFAULT;
+
+	out_be32(&priv->rxbd[ix].buf, dma);
+
+	return 0;
+}
+
 static int gfar_open(struct eth_device *edev)
 {
-	int ix;
 	struct gfar_private *priv = edev->priv;
 	struct gfar_phy *phy = priv->gfar_mdio;
 	void __iomem *regs = priv->regs;
-	int ret;
+	int ix, ret;
 
-	ret = phy_device_connect(edev, &phy->miibus, priv->phyaddr,
-				 gfar_adjust_link, 0, PHY_INTERFACE_MODE_NA);
+	ret = phy_device_connect(edev, (phy ? &phy->miibus : NULL), priv->phyaddr,
+				 gfar_adjust_link, 0, priv->interface);
 	if (ret)
 		return ret;
 
 	/* Point to the buffer descriptors */
-	out_be32(regs + GFAR_TBASE0_OFFSET, (unsigned int)priv->txbd);
-	out_be32(regs + GFAR_RBASE0_OFFSET, (unsigned int)priv->rxbd);
+	out_be32(regs + GFAR_TBASE0_OFFSET, virt_to_phys(priv->txbd));
+	out_be32(regs + GFAR_RBASE0_OFFSET, virt_to_phys(priv->rxbd));
 
 	/* Initialize the Rx Buffer descriptors */
 	for (ix = 0; ix < RX_BUF_CNT; ix++) {
 		out_be16(&priv->rxbd[ix].status, RXBD_EMPTY);
 		out_be16(&priv->rxbd[ix].length, 0);
-		out_be32(&priv->rxbd[ix].buf, (uint)priv->rx_buffer[ix]);
+		if (gfar_receive_packets_setup(priv, ix)) {
+			dev_err(&edev->dev, "RX packet dma mapping failed");
+			return -EIO;
+		}
 	}
 	out_be16(&priv->rxbd[RX_BUF_CNT - 1].status, RXBD_EMPTY | RXBD_WRAP);
 
@@ -324,26 +344,19 @@ static int gfar_bus_reset(struct mii_bus *bus)
 	return 0;
 }
 
-/* Reset the external PHYs. */
 static void gfar_init_phy(struct eth_device *dev)
 {
 	struct gfar_private *priv = dev->priv;
-	struct gfar_phy *phy = priv->gfar_mdio;
 	void __iomem *regs = priv->regs;
-	uint64_t start;
-
-	gfar_local_mdio_write(phy->regs, priv->phyaddr, GFAR_MIIM_CR,
-			GFAR_MIIM_CR_RST);
-
-	start = get_time_ns();
-	while (!is_timeout(start, 10 * MSECOND)) {
-		if (!(gfar_local_mdio_read(phy->regs, priv->phyaddr,
-					GFAR_MIIM_CR) & GFAR_MIIM_CR_RST))
-			break;
-	}
+	uint32_t ecntrl;
 
-	if (in_be32(regs + GFAR_ECNTRL_OFFSET) & GFAR_ECNTRL_SGMII_MODE)
+	ecntrl = in_be32(regs + GFAR_ECNTRL_OFFSET);
+	if (ecntrl & GFAR_ECNTRL_SGMII_MODE) {
+		priv->interface = PHY_INTERFACE_MODE_SGMII;
 		gfar_configure_serdes(priv);
+	} else if (ecntrl & ECNTRL_REDUCED_MODE) {
+		priv->interface = PHY_INTERFACE_MODE_RGMII;
+	}
 }
 
 static int gfar_send(struct eth_device *edev, void *packet, int length)
@@ -351,12 +364,19 @@ static int gfar_send(struct eth_device *edev, void *packet, int length)
 	struct gfar_private *priv = edev->priv;
 	void __iomem *regs = priv->regs;
 	struct device *dev = edev->parent;
+	dma_addr_t dma;
 	uint64_t start;
 	uint tidx;
 	uint16_t status;
 
 	tidx = priv->txidx;
-	out_be32(&priv->txbd[tidx].buf, (u32)packet);
+
+	dma = dma_map_single(dev, packet, length, DMA_TO_DEVICE);
+	if (dma_mapping_error(priv->dev, dma)) {
+		dev_err(dev, "TX mapping packet failed");
+		return -EFAULT;
+	}
+	out_be32(&priv->txbd[tidx].buf, (u32)dma);
 	out_be16(&priv->txbd[tidx].length, length);
 	out_be16(&priv->txbd[tidx].status,
 		in_be16(&priv->txbd[tidx].status) |
@@ -371,6 +391,7 @@ static int gfar_send(struct eth_device *edev, void *packet, int length)
 		if (is_timeout(start, 5 * MSECOND))
 			break;
 	}
+	dma_unmap_single(dev, dma, length, DMA_TO_DEVICE);
 
 	status = in_be16(&priv->txbd[tidx].status);
 	if (status & TXBD_READY) {
@@ -400,10 +421,18 @@ static void gfar_recv(struct eth_device *edev)
 
 	/* Send the packet up if there were no errors */
 	status = in_be16(&priv->rxbd[priv->rxidx].status);
-	if (!(status & RXBD_STATS))
-		net_receive(edev, priv->rx_buffer[priv->rxidx], length - 4);
-	else
+	if (!(status & RXBD_STATS)) {
+		void *frame;
+
+		frame = phys_to_virt(in_be32(&priv->rxbd[priv->rxidx].buf));
+		dma_sync_single_for_cpu(dev, (unsigned long)frame, length,
+					DMA_FROM_DEVICE);
+		net_receive(edev, frame, length - 4);
+		dma_sync_single_for_device(dev, (unsigned long)frame, length,
+					   DMA_FROM_DEVICE);
+	} else {
 		dev_err(dev, "Got error %x\n", status & RXBD_STATS);
+	}
 
 	out_be16(&priv->rxbd[priv->rxidx].length, 0);
 
@@ -450,33 +479,111 @@ static int gfar_miiphy_write(struct mii_bus *bus, int addr, int reg,
 	return 0;
 }
 
-/*
- * Initialize device structure. Returns success if
- * initialization succeeded.
- */
-static int gfar_probe(struct device *dev)
+#ifdef CONFIG_OFDEVICE
+static int gfar_probe_dt(struct gfar_private *priv)
 {
-	struct gfar_info_struct *gfar_info = dev->platform_data;
-	struct eth_device *edev;
-	struct gfar_private *priv;
-	struct device *mdev;
-	size_t size;
-	char devname[16];
-	char *p;
-	int ret;
+	struct device *dev = priv->dev;
+	struct device_node *np;
+	uint32_t tbiaddr = 0x1f;
+
+	priv->dev = dev;
+	if (IS_ERR(priv->regs)) {
+		struct device_node *child;
+
+		child = of_get_next_child(dev->device_node, NULL);
+		for_each_child_of_node(dev->device_node, child) {
+			if (child->name && !strncmp(child->name, "queue-group",
+					strlen("queue-group"))) {
+				priv->regs = of_iomap(child, 0);
+				if (IS_ERR(priv->regs)) {
+					dev_err(dev, "Failed to acquire first group address\n");
+					return -ENOENT;
+				}
+				break;
+			}
+		}
+	}
 
-	priv = xzalloc(sizeof(struct gfar_private));
+	priv->phyaddr = -1;
+	np = of_parse_phandle_from(dev->device_node, NULL, "phy-handle", 0);
+	if (np) {
+		uint32_t reg = 0;
 
-	ret = net_alloc_packets(priv->rx_buffer, ARRAY_SIZE(priv->rx_buffer));
-	if (ret)
-		return ret;
+		if (!of_property_read_u32(np, "reg", &reg))
+			priv->phyaddr = reg;
+	} else {
+		dev_err(dev, "Could not get phy-handle address\n");
+		return -ENOENT;
+	}
 
-	edev = &priv->edev;
+	priv->tbicr = TSEC_TBICR_SETTINGS;
+	priv->tbiana = TBIANA_SETTINGS;
+
+	/* Handle to tbi node */
+	np = of_parse_phandle_from(dev->device_node, NULL, "tbi-handle", 0);
+	if (np) {
+		struct device_node *parent;
+		struct gfar_phy *tbiphy;
+		struct device *bus_dev;
+		struct mii_bus *bus;
+
+		/* Get tbi address to be programmed in device */
+		if (of_property_read_u32(np, "reg", &tbiaddr)) {
+			dev_err(dev, "Failed to get tbi reg property\n");
+			return -ENOENT;
+		}
+		/* MDIO is the parent  */
+		parent = of_get_parent(np);
+		if (!parent)  {
+			dev_err(dev, "No parent node for TBI PHY?\n");
+			return -ENOENT;
+		}
+		tbiphy = xzalloc(sizeof(*tbiphy));
+		tbiphy->dev = parent->dev;
+		tbiphy->regs = NULL;
+
+		for_each_mii_bus(bus) {
+			if (bus->dev.of_node == parent) {
+				struct gfar_phy *phy;
+
+				bus_dev = bus->parent;
+				phy = bus_dev->priv;
+				tbiphy->regs = phy->regs;
+				break;
+			}
+		}
+		if (!tbiphy->regs) {
+			dev_err(dev, "Could not get TBI address\n");
+			free(tbiphy);
+			return PTR_ERR(tbiphy->regs);
+		}
+
+		tbiphy->miibus.read = gfar_miiphy_read;
+		tbiphy->miibus.write = gfar_miiphy_write;
+		tbiphy->miibus.priv = tbiphy;
+		tbiphy->miibus.parent = dev;
+		tbiphy->dev->priv = tbiphy;
+		priv->gfar_tbi = tbiphy;
+	}
+
+	priv->tbiaddr = tbiaddr;
+	out_be32(priv->regs + GFAR_TBIPA_OFFSET, priv->tbiaddr);
+
+	return 0;
+}
+
+static int gfar_probe_pd(struct gfar_private *priv)
+{
+	return -ENODEV;
+}
+#else
+static int gfar_probe_pd(struct gfar_private *priv)
+{
+	struct gfar_info_struct *gfar_info = priv->dev->platform_data;
+	struct device *mdev;
+	char devname[16];
 
 	priv->mdiobus_tbi = gfar_info->mdiobus_tbi;
-	priv->regs = dev_get_mem_region(dev, 0);
-	if (IS_ERR(priv->regs))
-		return PTR_ERR(priv->regs);
 	priv->phyaddr = gfar_info->phyaddr;
 	priv->tbicr = gfar_info->tbicr;
 	priv->tbiana = gfar_info->tbiana;
@@ -497,16 +604,65 @@ static int gfar_probe(struct device *dev)
 		}
 	}
 	priv->gfar_tbi = mdev->priv;
-	/*
-	 * Allocate descriptors 64-bit aligned. Descriptors
-	 * are 8 bytes in size.
-	 */
+
+	return 0;
+}
+
+static int gfar_probe_dt(struct gfar_private *priv)
+{
+	return -ENODEV;
+}
+#endif
+
+/*
+ * PPC only as there is no device tree support.
+ * Initialize device structure. Returns success if
+ * initialization succeeded.
+ */
+static int gfar_probe(struct device *dev)
+{
+	struct gfar_private *priv;
+	struct eth_device *edev;
+	size_t size;
+	void *base;
+	int ret;
+
+	priv = xzalloc(sizeof(struct gfar_private));
+
+	ret = net_alloc_packets(priv->rx_buffer, ARRAY_SIZE(priv->rx_buffer));
+	if (ret)
+		goto free_priv;
+
+	priv->dev = dev;
+	edev = &priv->edev;
+
+	priv->regs = dev_get_mem_region(dev, 0);
+	if (IS_ERR(priv->regs)) {
+		ret = PTR_ERR(priv->regs);
+		goto free_received_packets;
+	}
+
+	if (dev->of_node) {
+		ret = gfar_probe_dt(priv);
+		if (ret)
+			goto free_received_packets;
+	} else {
+		ret = gfar_probe_pd(priv);
+		if (ret)
+			goto free_received_packets;
+	}
+
 	size = ((TX_BUF_CNT * sizeof(struct txbd8)) +
-		(RX_BUF_CNT * sizeof(struct rxbd8))) + BUF_ALIGN;
-	p = (char *)xmemalign(BUF_ALIGN, size);
-	priv->txbd = (struct txbd8 __iomem *)p;
-	priv->rxbd = (struct rxbd8 __iomem *)(p +
-			(TX_BUF_CNT * sizeof(struct txbd8)));
+			(RX_BUF_CNT * sizeof(struct rxbd8)));
+	if (IS_ENABLED(CONFIG_PPC)) {
+		base = xmemalign(BUF_ALIGN, size);
+	} else {
+		base = dma_alloc_coherent(DMA_DEVICE_BROKEN, size, DMA_ADDRESS_BROKEN);
+		dma_set_mask(dev, DMA_BIT_MASK(32));
+	}
+	priv->txbd = (struct txbd8 __iomem *)base;
+	base += TX_BUF_CNT * sizeof(struct txbd8);
+	priv->rxbd = (struct rxbd8 __iomem *)base;
 
 	edev->priv = priv;
 	edev->init = gfar_init;
@@ -525,22 +681,56 @@ static int gfar_probe(struct device *dev)
 	gfar_init_phy(edev);
 
 	return eth_register(edev);
+
+free_received_packets:
+	free(priv->rx_buffer);
+free_priv:
+	free(priv);
+
+	return ret;
 }
 
+static struct tsec_data etsec2_data = {
+	.mdio_regs_off = 0x520,
+};
+
+static struct tsec_data gianfar_data = {
+	.mdio_regs_off = 0x0,
+};
+
+static const struct of_device_id gfar_ids[] = {
+	{ .compatible = "fsl,etsec2", .data = &etsec2_data },
+	{ .compatible = "gianfar", .data = &gianfar_data },
+	{ /* sentinel */ }
+};
+
 static struct driver gfar_eth_driver = {
 	.name  = "gfar",
+	.of_compatible = DRV_OF_COMPAT(gfar_ids),
 	.probe = gfar_probe,
 };
 device_platform_driver(gfar_eth_driver);
 
+/* MII bus */
+static struct fsl_pq_mdio_data mdio_gianfar_data = {
+	.mdio_regs_off = 0x0,
+};
+
+static __maybe_unused const struct of_device_id gfar_mdio_ids[] = {
+	{ .compatible = "fsl,etsec2-mdio", .data = &mdio_gianfar_data },
+	{ /* sentinel */ }
+};
+
 static int gfar_phy_probe(struct device *dev)
 {
 	struct gfar_phy *phy;
+	struct fsl_pq_mdio_data *data;
 	int ret;
 
+	data = (struct fsl_pq_mdio_data *)device_get_match_data(dev);
 	phy = xzalloc(sizeof(*phy));
 	phy->dev = dev;
-	phy->regs = dev_get_mem_region(dev, 0);
+	phy->regs = dev_get_mem_region(dev, 0) + data->mdio_regs_off;
 	if (IS_ERR(phy->regs))
 		return PTR_ERR(phy->regs);
 
@@ -560,10 +750,12 @@ static int gfar_phy_probe(struct device *dev)
 
 static struct driver gfar_phy_driver = {
 	.name  = "gfar-mdio",
+	.of_compatible = DRV_OF_COMPAT(gfar_mdio_ids),
 	.probe = gfar_phy_probe,
 };
 register_driver_macro(coredevice, platform, gfar_phy_driver);
 
+#ifndef CONFIG_OFDEVICE
 static int gfar_tbiphy_probe(struct device *dev)
 {
 	struct gfar_phy *phy;
@@ -593,3 +785,4 @@ static struct driver gfar_tbiphy_driver = {
 	.probe = gfar_tbiphy_probe,
 };
 register_driver_macro(coredevice, platform, gfar_tbiphy_driver);
+#endif
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index acb50b9ce3..4e364fdf1a 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -14,8 +14,14 @@
 #define __GIANFAR_H
 
 #include <net.h>
+
+#ifdef CONFIG_PPC
 #include <asm/config.h>
+#endif
+
+#ifdef CONFIG_ARCH_MPC85XX
 #include <mach/gianfar.h>
+#endif
 
 #define MAC_ADDR_LEN 6
 
@@ -27,6 +33,10 @@
 #define GFAR_TBI_ANEX		0x06
 #define GFAR_TBI_TBICON		0x11
 
+#ifndef GFAR_TBIPA_OFFSET
+#define GFAR_TBIPA_OFFSET       0x030
+#endif
+
 /* TBI MDIO register bit fields*/
 #define GFAR_TBICON_CLK_SELECT		0x0020
 #define GFAR_TBIANA_ASYMMETRIC_PAUSE	0x0100
@@ -64,7 +74,9 @@
 
 #define ECNTRL_INIT_SETTINGS		0x00001000
 #define GFAR_ECNTRL_TBI_MODE		0x00000020
+#define ECNTRL_REDUCED_MODE		0x00000010
 #define GFAR_ECNTRL_R100		0x00000008
+#define GFAR_ECNTRL_RMM			0x00000004
 #define GFAR_ECNTRL_SGMII_MODE		0x00000002
 
 #ifndef GFAR_TBIPA_VALUE
@@ -271,9 +283,11 @@ struct gfar_phy {
 #define BUF_ALIGN	8
 
 struct gfar_private {
+	struct device_d *dev;
 	struct eth_device edev;
 	void __iomem *regs;
 	int mdiobus_tbi;
+	phy_interface_t interface;
 	struct gfar_phy *gfar_mdio;
 	struct gfar_phy *gfar_tbi;
 	struct phy_info *phyinfo;
@@ -284,9 +298,31 @@ struct gfar_private {
 	uint phyaddr;
 	uint tbicr;
 	uint tbiana;
+	uint tbiaddr;
 	uint link;
 	uint duplexity;
 	uint speed;
 	void *rx_buffer[PKTBUFSRX];
 };
+
+struct tsec_data {
+	uint32_t mdio_regs_off;
+};
+
+struct fsl_pq_mdio_data {
+	uint32_t mdio_regs_off;
+};
+
+#define TBIANA_SETTINGS ( \
+	GFAR_TBIANA_ASYMMETRIC_PAUSE \
+	| GFAR_TBIANA_SYMMETRIC_PAUSE \
+	| GFAR_TBIANA_FULL_DUPLEX \
+	)
+
+#define TSEC_TBICR_SETTINGS ( \
+	GFAR_TBICR_PHY_RESET \
+	| GFAR_TBICR_ANEG_ENABLE \
+	| GFAR_TBICR_FULL_DUPLEX \
+	| GFAR_TBICR_SPEED1_SET \
+	)
 #endif /* __GIANFAR_H */
-- 
2.43.0




^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 4/4] ARM: ls1021a: initial Ethernet and mdio configuration
  2026-02-04 11:46 [PATCH v2 0/4] net: expand gianfar support to ls1021a Renaud Barbier
                   ` (2 preceding siblings ...)
  2026-02-04 11:46 ` [PATCH v2 3/4] net:gianfar: add device tree support Renaud Barbier
@ 2026-02-04 11:46 ` Renaud Barbier
  2026-02-09 14:43   ` Sascha Hauer
  3 siblings, 1 reply; 7+ messages in thread
From: Renaud Barbier @ 2026-02-04 11:46 UTC (permalink / raw)
  To: barebox; +Cc: Renaud Barbier

Enable the use of the Ethernet port 1 (none other tested).
The PHY is limited to use 100FD as 1000FD is failing.

Signed-off-by: Renaud Barbier <renaud.barbier@ametek.com>
---
 arch/arm/boards/ls1021aiot/board.c       | 35 ++++++++++++++++++++++++
 arch/arm/configs/layerscape_v7_defconfig |  7 +++++
 arch/arm/dts/fsl-ls1021a-iot.dts         | 28 +++++++++++++++++++
 3 files changed, 70 insertions(+)

diff --git a/arch/arm/boards/ls1021aiot/board.c b/arch/arm/boards/ls1021aiot/board.c
index 70070a4e75..d4976ebc80 100644
--- a/arch/arm/boards/ls1021aiot/board.c
+++ b/arch/arm/boards/ls1021aiot/board.c
@@ -20,6 +20,39 @@
 #include <of_address.h>
 #include <soc/fsl/immap_lsch2.h>
 
+#define PHY_ID_AR8031	0x004dd074
+
+/* Currently 1000FD is not working. Below is a bit of guess work
+ * from reading MMD3/MMD7 of the AR8033
+ */
+static int phy_fixup(struct phy_device *phydev)
+{
+	unsigned short val;
+	int advertise = SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half;
+
+	phydev->advertising &= ~advertise;
+
+	/* Ar8031 phy SmartEEE feature cause link status generates glitch,
+	 * which cause ethernet link down/up issue, so disable SmartEEE
+	 */
+	phy_write(phydev, 0xd, 0x3);
+	phy_write(phydev, 0xe, 0x805d);
+	phy_write(phydev, 0xd, 0x4003);
+	val = phy_read(phydev, 0xe);
+	val &= ~(0x1 << 8);
+	phy_write(phydev, 0xe, val);
+
+	/* Use XTAL */
+	phy_write(phydev, 0xd, 0x7);
+	phy_write(phydev, 0xe, 0x8016);
+	phy_write(phydev, 0xd, 0x4007);
+	val = phy_read(phydev, 0xe);
+	val &= 0xffe3;
+	phy_write(phydev, 0xe, val);
+
+	return 0;
+}
+
 static int iot_mem_init(void)
 {
 	if (!of_machine_is_compatible("fsl,ls1021a"))
@@ -42,6 +75,8 @@ static int iot_postcore_init(void)
 	clrbits_be32(&scfg->etsecdmamcr, SCFG_ETSECDMAMCR_LE_BD_FR);
 	out_be32(&scfg->etsecmcr, SCFG_ETSECCMCR_GE2_CLK125);
 
+	phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff, phy_fixup);
+
 	return 0;
 }
 coredevice_initcall(iot_postcore_init);
diff --git a/arch/arm/configs/layerscape_v7_defconfig b/arch/arm/configs/layerscape_v7_defconfig
index 5127a52522..99570a8890 100644
--- a/arch/arm/configs/layerscape_v7_defconfig
+++ b/arch/arm/configs/layerscape_v7_defconfig
@@ -45,6 +45,10 @@ CONFIG_CMD_LET=y
 CONFIG_CMD_MSLEEP=y
 CONFIG_CMD_READF=y
 CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
 CONFIG_CMD_ECHO_E=y
 CONFIG_CMD_EDIT=y
 CONFIG_CMD_MENU=y
@@ -67,6 +71,8 @@ CONFIG_CMD_OF_NODE=y
 CONFIG_CMD_OF_PROPERTY=y
 CONFIG_CMD_OFTREE=y
 CONFIG_CMD_TIME=y
+CONFIG_NET=y
+CONFIG_DRIVER_NET_GIANFAR=y
 CONFIG_OF_BAREBOX_DRIVERS=y
 CONFIG_DRIVER_SERIAL_NS16550=y
 CONFIG_DRIVER_SPI_FSL_QUADSPI=y
@@ -85,3 +91,4 @@ CONFIG_EEPROM_AT24=y
 CONFIG_GPIO_PCA953X=y
 CONFIG_ZLIB=y
 CONFIG_LZO_DECOMPRESS=y
+CONFIG_FS_TFTP=y
diff --git a/arch/arm/dts/fsl-ls1021a-iot.dts b/arch/arm/dts/fsl-ls1021a-iot.dts
index d7e8bcc7ed..33282c8f52 100644
--- a/arch/arm/dts/fsl-ls1021a-iot.dts
+++ b/arch/arm/dts/fsl-ls1021a-iot.dts
@@ -69,6 +69,34 @@ &i2c2 {
 	status = "disabled";
 };
 
+&enet0 {
+	status = "disabled";
+};
+
+&enet1 {
+	tbi-handle = <&tbi1>;
+	phy-handle = <&phy3>;
+	phy-mode = "sgmii";
+	/* Disable property as transmit fails without a DMA sync */
+	/delete-property/ dma-coherent;
+};
+
+&enet2 {
+	status = "disabled";
+};
+
+&mdio0 {
+	/* Rename the compatible name property as the mdio register offset
+	 * in the gianfar driver depends on this name. Once the driver
+	 * is in sync with Linux, it may be gone.
+	 */
+	compatible = "fsl,etsec2-mdio";
+};
+
+&mdio1 {
+	compatible = "fsl,etsec2-mdio";
+};
+
 &uart0 {
 	status = "okay";
 	clock-frequency = <150000000>;
-- 
2.43.0




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 4/4] ARM: ls1021a: initial Ethernet and mdio configuration
  2026-02-04 11:46 ` [PATCH v2 4/4] ARM: ls1021a: initial Ethernet and mdio configuration Renaud Barbier
@ 2026-02-09 14:43   ` Sascha Hauer
  2026-02-09 17:46     ` Renaud Barbier
  0 siblings, 1 reply; 7+ messages in thread
From: Sascha Hauer @ 2026-02-09 14:43 UTC (permalink / raw)
  To: Renaud Barbier; +Cc: barebox

Hi Renaud,

On Wed, Feb 04, 2026 at 11:46:21AM +0000, Renaud Barbier wrote:
> diff --git a/arch/arm/dts/fsl-ls1021a-iot.dts b/arch/arm/dts/fsl-ls1021a-iot.dts
> index d7e8bcc7ed..33282c8f52 100644
> --- a/arch/arm/dts/fsl-ls1021a-iot.dts
> +++ b/arch/arm/dts/fsl-ls1021a-iot.dts
> @@ -69,6 +69,34 @@ &i2c2 {
>  	status = "disabled";
>  };
>  
> +&enet0 {
> +	status = "disabled";
> +};
> +
> +&enet1 {
> +	tbi-handle = <&tbi1>;
> +	phy-handle = <&phy3>;
> +	phy-mode = "sgmii";
> +	/* Disable property as transmit fails without a DMA sync */
> +	/delete-property/ dma-coherent;
> +};
> +
> +&enet2 {
> +	status = "disabled";
> +};
> +
> +&mdio0 {
> +	/* Rename the compatible name property as the mdio register offset
> +	 * in the gianfar driver depends on this name. Once the driver
> +	 * is in sync with Linux, it may be gone.
> +	 */
> +	compatible = "fsl,etsec2-mdio";

What am I missing here? The "fsl,etsec2-mdio" compatible is introduced
in your patch series and the original "gianfar" compatible is unused in
barebox, so why not use the original "gianfar" compatible?

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH v2 4/4] ARM: ls1021a: initial Ethernet and mdio configuration
  2026-02-09 14:43   ` Sascha Hauer
@ 2026-02-09 17:46     ` Renaud Barbier
  0 siblings, 0 replies; 7+ messages in thread
From: Renaud Barbier @ 2026-02-09 17:46 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox



> > +&enet0 {
> > +     status = "disabled";
> > +};
> > +
> > +&enet1 {
> > +     tbi-handle = <&tbi1>;
> > +     phy-handle = <&phy3>;
> > +     phy-mode = "sgmii";
> > +     /* Disable property as transmit fails without a DMA sync */
> > +     /delete-property/ dma-coherent;
> > +};
> > +
> > +&enet2 {
> > +     status = "disabled";
> > +};
> > +
> > +&mdio0 {
> > +     /* Rename the compatible name property as the mdio register offset
> > +      * in the gianfar driver depends on this name. Once the driver
> > +      * is in sync with Linux, it may be gone.
> > +      */
> > +     compatible = "fsl,etsec2-mdio";
> 
> What am I missing here? The "fsl,etsec2-mdio" compatible is introduced in
> your patch series and the original "gianfar" compatible is unused in barebox,
> so why not use the original "gianfar" compatible?

This looks like a brain meltdown. Working on it.

> 
> Sascha
> 
> --
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       |
> https://urldefense.com/v3/__http://www.pengutronix.de/__;!!HKOSU0g!EYn
> wk0KOC4uaZ6o2g405vX9jY5cYxTXggB3OWKRK4fkhKYQkD1ipDYAvpoXwCD1xI
> ouD69egxnltsNg0UUl0r8QgLw$   |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-02-09 17:46 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-04 11:46 [PATCH v2 0/4] net: expand gianfar support to ls1021a Renaud Barbier
2026-02-04 11:46 ` [PATCH v2 1/4] net: gianfar: disable link information Renaud Barbier
2026-02-04 11:46 ` [PATCH v2 2/4] gianfar: apply checkpatch recommendations Renaud Barbier
2026-02-04 11:46 ` [PATCH v2 3/4] net:gianfar: add device tree support Renaud Barbier
2026-02-04 11:46 ` [PATCH v2 4/4] ARM: ls1021a: initial Ethernet and mdio configuration Renaud Barbier
2026-02-09 14:43   ` Sascha Hauer
2026-02-09 17:46     ` Renaud Barbier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox