mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v3 0/4] net: expand gianfar support to ls1021a
@ 2026-02-10 12:52 Renaud Barbier
  2026-02-10 12:52 ` [PATCH v3 1/4] net: gianfar: disable link information Renaud Barbier
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Renaud Barbier @ 2026-02-10 12:52 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.

In this version 3, remove code that was meant to make the difference
between the mdio register offset between PPC and ARM if retrieved from
the device tree. However, the PPC platform does not support DTBs and the
mdio offset is already taken into account into the mdio access functions.
Hence, the clean up.

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         |  16 ++
 arch/powerpc/include/asm/dma.h           |  34 +++
 drivers/net/Kconfig                      |   2 +-
 drivers/net/gianfar.c                    | 310 ++++++++++++++++++-----
 drivers/net/gianfar.h                    |  32 ++-
 7 files changed, 367 insertions(+), 69 deletions(-)

-- 
2.43.0




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

* [PATCH v3 1/4] net: gianfar: disable link information
  2026-02-10 12:52 [PATCH v3 0/4] net: expand gianfar support to ls1021a Renaud Barbier
@ 2026-02-10 12:52 ` Renaud Barbier
  2026-02-10 12:52 ` [PATCH v3 2/4] gianfar: apply checkpatch recommendations Renaud Barbier
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Renaud Barbier @ 2026-02-10 12:52 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] 6+ messages in thread

* [PATCH v3 2/4] gianfar: apply checkpatch recommendations
  2026-02-10 12:52 [PATCH v3 0/4] net: expand gianfar support to ls1021a Renaud Barbier
  2026-02-10 12:52 ` [PATCH v3 1/4] net: gianfar: disable link information Renaud Barbier
@ 2026-02-10 12:52 ` Renaud Barbier
  2026-02-10 12:52 ` [PATCH v3 3/4] net:gianfar: add device tree support Renaud Barbier
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Renaud Barbier @ 2026-02-10 12:52 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] 6+ messages in thread

* [PATCH v3 3/4] net:gianfar: add device tree support
  2026-02-10 12:52 [PATCH v3 0/4] net: expand gianfar support to ls1021a Renaud Barbier
  2026-02-10 12:52 ` [PATCH v3 1/4] net: gianfar: disable link information Renaud Barbier
  2026-02-10 12:52 ` [PATCH v3 2/4] gianfar: apply checkpatch recommendations Renaud Barbier
@ 2026-02-10 12:52 ` Renaud Barbier
  2026-02-10 12:52 ` [PATCH v3 4/4] ARM: ls1021a: initial Ethernet and mdio configuration Renaud Barbier
  2026-02-11  9:35 ` [PATCH v3 0/4] net: expand gianfar support to ls1021a Sascha Hauer
  4 siblings, 0 replies; 6+ messages in thread
From: Renaud Barbier @ 2026-02-10 12:52 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          | 289 ++++++++++++++++++++++++++-------
 drivers/net/gianfar.h          |  28 ++++
 4 files changed, 297 insertions(+), 56 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..cd43b29f40 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,19 +681,39 @@ 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 const struct of_device_id gfar_ids[] = {
+	{ .compatible = "fsl,etsec2" },
+	{ /* 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);
 
+static __maybe_unused const struct of_device_id gfar_mdio_ids[] = {
+	{ .compatible = "gianfar" },
+	{ /* 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);
@@ -560,10 +736,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 +771,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..545cd26ebc 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,23 @@ struct gfar_private {
 	uint phyaddr;
 	uint tbicr;
 	uint tbiana;
+	uint tbiaddr;
 	uint link;
 	uint duplexity;
 	uint speed;
 	void *rx_buffer[PKTBUFSRX];
 };
+
+#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] 6+ messages in thread

* [PATCH v3 4/4] ARM: ls1021a: initial Ethernet and mdio configuration
  2026-02-10 12:52 [PATCH v3 0/4] net: expand gianfar support to ls1021a Renaud Barbier
                   ` (2 preceding siblings ...)
  2026-02-10 12:52 ` [PATCH v3 3/4] net:gianfar: add device tree support Renaud Barbier
@ 2026-02-10 12:52 ` Renaud Barbier
  2026-02-11  9:35 ` [PATCH v3 0/4] net: expand gianfar support to ls1021a Sascha Hauer
  4 siblings, 0 replies; 6+ messages in thread
From: Renaud Barbier @ 2026-02-10 12:52 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         | 16 +++++++++++
 3 files changed, 58 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..fdc7c4f879 100644
--- a/arch/arm/dts/fsl-ls1021a-iot.dts
+++ b/arch/arm/dts/fsl-ls1021a-iot.dts
@@ -69,6 +69,22 @@ &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";
+};
+
 &uart0 {
 	status = "okay";
 	clock-frequency = <150000000>;
-- 
2.43.0




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

* Re: [PATCH v3 0/4] net: expand gianfar support to ls1021a
  2026-02-10 12:52 [PATCH v3 0/4] net: expand gianfar support to ls1021a Renaud Barbier
                   ` (3 preceding siblings ...)
  2026-02-10 12:52 ` [PATCH v3 4/4] ARM: ls1021a: initial Ethernet and mdio configuration Renaud Barbier
@ 2026-02-11  9:35 ` Sascha Hauer
  4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2026-02-11  9:35 UTC (permalink / raw)
  To: barebox, Renaud Barbier


On Tue, 10 Feb 2026 12:52:21 +0000, Renaud Barbier wrote:
> 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.
> 
> In this version 3, remove code that was meant to make the difference
> between the mdio register offset between PPC and ARM if retrieved from
> the device tree. However, the PPC platform does not support DTBs and the
> mdio offset is already taken into account into the mdio access functions.
> Hence, the clean up.
> 
> [...]

Applied, thanks!

[1/4] net: gianfar: disable link information
      https://git.pengutronix.de/cgit/barebox/commit/?id=f532dc064126 (link may not be stable)
[2/4] gianfar: apply checkpatch recommendations
      https://git.pengutronix.de/cgit/barebox/commit/?id=9af9cb22a97f (link may not be stable)
[3/4] net:gianfar: add device tree support
      https://git.pengutronix.de/cgit/barebox/commit/?id=49b79bb5e566 (link may not be stable)
[4/4] ARM: ls1021a: initial Ethernet and mdio configuration
      https://git.pengutronix.de/cgit/barebox/commit/?id=7d789e0de5a1 (link may not be stable)

Best regards,
-- 
Sascha Hauer <s.hauer@pengutronix.de>




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

end of thread, other threads:[~2026-02-11  9:35 UTC | newest]

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

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