* [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", ®))
+ 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