[PATCH 0/2] Add support for 10G/25G to AXI emac driver

STALE1938d

9 messages, 4 authors, 2021-06-29 · open the first message on its own page

[PATCH 0/2] Add support for 10G/25G to AXI emac driver

From: Ashok Reddy Soma <hidden>
Date: 2021-06-24 06:34:59

 - Cleanup of_to_plat() to access platform data only in it
 - Copy plat data to priv data in probe function
 - Add support for 10G/25G to the AXI emac driver
 - Keep all phy related activity in the driver for 1G only


Ashok Reddy Soma (2):
  net: xilinx: axi_emac: Cleanup of of_to_plat()
  net: xilinx: axi_emac: Add support for 10G/25G AXI ethernet

 drivers/net/xilinx_axi_emac.c | 193 +++++++++++++++++++++++++---------
 1 file changed, 142 insertions(+), 51 deletions(-)

-- 
2.17.1

[PATCH 1/2] net: xilinx: axi_emac: Cleanup of of_to_plat()

From: Ashok Reddy Soma <hidden>
Date: 2021-06-24 06:35:13

There are lot of accesses to priv data in of_to_plat(), which is incorrect.
Create a platform data structure and use it in of_to_plat(), then copy all
platform data to priv data in probe.

Signed-off-by: Ashok Reddy Soma <redacted>
---

 drivers/net/xilinx_axi_emac.c | 47 ++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 15 deletions(-)
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index 2ce6271afe..cfc6082475 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -87,6 +87,16 @@ struct axidma_reg {
 	u32 tail_hi; /* TAILDESC high 32 bit */
 };
 
+/* Platform data structures */
+struct axidma_plat {
+	struct eth_pdata eth_pdata;
+	struct axidma_reg *dmatx;
+	struct axidma_reg *dmarx;
+	int phyaddr;
+	u8 eth_hasnobuf;
+	int phy_of_handle;
+};
+
 /* Private driver structures */
 struct axidma_priv {
 	struct axidma_reg *dmatx;
@@ -690,9 +700,20 @@ static int axiemac_miiphy_write(struct mii_dev *bus, int addr, int devad,
 
 static int axi_emac_probe(struct udevice *dev)
 {
+	struct axidma_plat *plat = dev_get_plat(dev);
+	struct eth_pdata *pdata = &plat->eth_pdata;
 	struct axidma_priv *priv = dev_get_priv(dev);
 	int ret;
 
+	priv->iobase = (struct axi_regs *)pdata->iobase;
+	priv->dmatx = plat->dmatx;
+	/* RX channel offset is 0x30 */
+	priv->dmarx = (struct axidma_reg *)((phys_addr_t)priv->dmatx + 0x30);
+	priv->eth_hasnobuf = plat->eth_hasnobuf;
+	priv->phyaddr = plat->phyaddr;
+	priv->phy_of_handle = plat->phy_of_handle;
+	priv->interface = pdata->phy_interface;
+
 	priv->bus = mdio_alloc();
 	priv->bus->read = axiemac_miiphy_read;
 	priv->bus->write = axiemac_miiphy_write;
@@ -729,14 +750,13 @@ static const struct eth_ops axi_emac_ops = {
 
 static int axi_emac_of_to_plat(struct udevice *dev)
 {
-	struct eth_pdata *pdata = dev_get_plat(dev);
-	struct axidma_priv *priv = dev_get_priv(dev);
+	struct axidma_plat *plat = dev_get_plat(dev);
+	struct eth_pdata *pdata = &plat->eth_pdata;
 	int node = dev_of_offset(dev);
 	int offset = 0;
 	const char *phy_mode;
 
 	pdata->iobase = dev_read_addr(dev);
-	priv->iobase = (struct axi_regs *)pdata->iobase;
 
 	offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
 				       "axistream-connected");
@@ -744,21 +764,19 @@ static int axi_emac_of_to_plat(struct udevice *dev)
 		printf("%s: axistream is not found\n", __func__);
 		return -EINVAL;
 	}
-	priv->dmatx = (struct axidma_reg *)fdtdec_get_addr(gd->fdt_blob,
+	plat->dmatx = (struct axidma_reg *)fdtdec_get_addr(gd->fdt_blob,
 							  offset, "reg");
-	if (!priv->dmatx) {
+	if (!plat->dmatx) {
 		printf("%s: axi_dma register space not found\n", __func__);
 		return -EINVAL;
 	}
-	/* RX channel offset is 0x30 */
-	priv->dmarx = (struct axidma_reg *)((phys_addr_t)priv->dmatx + 0x30);
 
-	priv->phyaddr = -1;
+	plat->phyaddr = -1;
 
 	offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy-handle");
 	if (offset > 0) {
-		priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
-		priv->phy_of_handle = offset;
+		plat->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
+		plat->phy_of_handle = offset;
 	}
 
 	phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
@@ -768,13 +786,12 @@ static int axi_emac_of_to_plat(struct udevice *dev)
 		printf("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
 		return -EINVAL;
 	}
-	priv->interface = pdata->phy_interface;
 
-	priv->eth_hasnobuf = fdtdec_get_bool(gd->fdt_blob, node,
+	plat->eth_hasnobuf = fdtdec_get_bool(gd->fdt_blob, node,
 					     "xlnx,eth-hasnobuf");
 
-	printf("AXI EMAC: %lx, phyaddr %d, interface %s\n", (ulong)priv->iobase,
-	       priv->phyaddr, phy_string_for_interface(priv->interface));
+	printf("AXI EMAC: %lx, phyaddr %d, interface %s\n", (ulong)pdata->iobase,
+	       plat->phyaddr, phy_string_for_interface(pdata->phy_interface));
 
 	return 0;
 }
@@ -793,5 +810,5 @@ U_BOOT_DRIVER(axi_emac) = {
 	.remove	= axi_emac_remove,
 	.ops	= &axi_emac_ops,
 	.priv_auto	= sizeof(struct axidma_priv),
-	.plat_auto	= sizeof(struct eth_pdata),
+	.plat_auto	= sizeof(struct axidma_plat),
 };
-- 
2.17.1

[PATCH 2/2] net: xilinx: axi_emac: Add support for 10G/25G AXI ethernet

From: Ashok Reddy Soma <hidden>
Date: 2021-06-24 06:35:24

Add support for 10G/25G (XXV) high speed ethernet. This Makes use of
the exiting AXI DMA, similar to 1G.

Signed-off-by: Alessandro Temil <redacted>
Signed-off-by: Ashok Reddy Soma <redacted>
---

 drivers/net/xilinx_axi_emac.c | 162 +++++++++++++++++++++++++---------
 1 file changed, 118 insertions(+), 44 deletions(-)
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index cfc6082475..2ec76d0f52 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
+ * Copyright (C) 2021 Waymo LLC
  * Copyright (C) 2011 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2011 PetaLogix
  * Copyright (C) 2010 Xilinx, Inc. All rights reserved.
@@ -73,9 +74,22 @@ DECLARE_GLOBAL_DATA_PTR;
 #define XAXIDMA_BD_CTRL_TXSOF_MASK	0x08000000 /* First tx packet */
 #define XAXIDMA_BD_CTRL_TXEOF_MASK	0x04000000 /* Last tx packet */
 
-#define DMAALIGN	128
+/* Bitmasks for XXV Ethernet MAC */
+#define XXV_TC_TX_MASK		0x00000001
+#define XXV_TC_FCS_MASK		0x00000002
+#define XXV_RCW1_RX_MASK	0x00000001
+#define XXV_RCW1_FCS_MASK	0x00000002
+
+#define DMAALIGN		128
+#define XXV_MIN_PKT_SIZE	60
 
 static u8 rxframe[PKTSIZE_ALIGN] __attribute((aligned(DMAALIGN)));
+static u8 txminframe[XXV_MIN_PKT_SIZE] __attribute((aligned(DMAALIGN)));
+
+enum emac_variant {
+	EMAC_1G = 0,
+	EMAC_10G_25G = 1,
+};
 
 /* Reflect dma offsets */
 struct axidma_reg {
@@ -95,6 +109,7 @@ struct axidma_plat {
 	int phyaddr;
 	u8 eth_hasnobuf;
 	int phy_of_handle;
+	enum emac_variant mactype;
 };
 
 /* Private driver structures */
@@ -108,6 +123,7 @@ struct axidma_priv {
 	struct mii_dev *bus;
 	u8 eth_hasnobuf;
 	int phy_of_handle;
+	enum emac_variant mactype;
 };
 
 /* BD descriptors */
@@ -154,6 +170,14 @@ struct axi_regs {
 	u32 uaw1; /* 0x704: Unicast address word 1 */
 };
 
+struct xxv_axi_regs {
+	u32 gt_reset;	/* 0x0 */
+	u32 reserved[2];
+	u32 tc;		/* 0xC: Tx Configuration */
+	u32 reserved2;
+	u32 rcw1;	/* 0x14: Rx Configuration Word 1 */
+};
+
 /* Use MII register 1 (MII status register) to detect PHY */
 #define PHY_DETECT_REG  1
 
@@ -385,6 +409,18 @@ static void axiemac_stop(struct udevice *dev)
 	debug("axiemac: Halted\n");
 }
 
+static int xxv_axi_ethernet_init(struct axidma_priv *priv)
+{
+	struct xxv_axi_regs *regs = (struct xxv_axi_regs *)priv->iobase;
+
+	writel(readl(&regs->rcw1) | XXV_RCW1_FCS_MASK, &regs->rcw1);
+	writel(readl(&regs->tc) | XXV_TC_FCS_MASK, &regs->tc);
+	writel(readl(&regs->tc) | XXV_TC_TX_MASK, &regs->tc);
+	writel(readl(&regs->rcw1) | XXV_RCW1_RX_MASK, &regs->rcw1);
+
+	return 0;
+}
+
 static int axi_ethernet_init(struct axidma_priv *priv)
 {
 	struct axi_regs *regs = priv->iobase;
@@ -440,6 +476,9 @@ static int axiemac_write_hwaddr(struct udevice *dev)
 	struct axidma_priv *priv = dev_get_priv(dev);
 	struct axi_regs *regs = priv->iobase;
 
+	if (priv->mactype != EMAC_1G)
+		return 0;
+
 	/* Set the MAC address */
 	int val = ((pdata->enetaddr[3] << 24) | (pdata->enetaddr[2] << 16) |
 		(pdata->enetaddr[1] << 8) | (pdata->enetaddr[0]));
@@ -477,7 +516,6 @@ static void axi_dma_init(struct axidma_priv *priv)
 static int axiemac_start(struct udevice *dev)
 {
 	struct axidma_priv *priv = dev_get_priv(dev);
-	struct axi_regs *regs = priv->iobase;
 	u32 temp;
 
 	debug("axiemac: Init started\n");
@@ -490,8 +528,13 @@ static int axiemac_start(struct udevice *dev)
 	axi_dma_init(priv);
 
 	/* Initialize AxiEthernet hardware. */
-	if (axi_ethernet_init(priv))
-		return -1;
+	if (priv->mactype == EMAC_1G) {
+		if (axi_ethernet_init(priv))
+			return -1;
+	} else {
+		if (xxv_axi_ethernet_init(priv))
+			return -1;
+	}
 
 	/* Disable all RX interrupts before RxBD space setup */
 	temp = readl(&priv->dmarx->control);
@@ -525,15 +568,25 @@ static int axiemac_start(struct udevice *dev)
 	/* Rx BD is ready - start */
 	axienet_dma_write(&rx_bd, &priv->dmarx->tail);
 
-	/* Enable TX */
-	writel(XAE_TC_TX_MASK, &regs->tc);
-	/* Enable RX */
-	writel(XAE_RCW1_RX_MASK, &regs->rcw1);
+	if (priv->mactype == EMAC_1G) {
+		struct axi_regs *regs = priv->iobase;
+		/* Enable TX */
+		writel(XAE_TC_TX_MASK, &regs->tc);
+		/* Enable RX */
+		writel(XAE_RCW1_RX_MASK, &regs->rcw1);
+
+		/* PHY setup */
+		if (!setup_phy(dev)) {
+			axiemac_stop(dev);
+			return -1;
+		}
+	} else {
+		struct xxv_axi_regs *regs = (struct xxv_axi_regs *)priv->iobase;
+		/* Enable TX */
+		writel(readl(&regs->tc) | XXV_TC_TX_MASK, &regs->tc);
 
-	/* PHY setup */
-	if (!setup_phy(dev)) {
-		axiemac_stop(dev);
-		return -1;
+		/* Enable RX */
+		writel(readl(&regs->rcw1) | XXV_RCW1_RX_MASK, &regs->rcw1);
 	}
 
 	debug("axiemac: Init complete\n");
@@ -548,6 +601,14 @@ static int axiemac_send(struct udevice *dev, void *ptr, int len)
 	if (len > PKTSIZE_ALIGN)
 		len = PKTSIZE_ALIGN;
 
+	/* If size is less than min packet size, pad to min size */
+	if (priv->mactype == EMAC_10G_25G && len < XXV_MIN_PKT_SIZE) {
+		memset(txminframe, 0, XXV_MIN_PKT_SIZE);
+		memcpy(txminframe, ptr, len);
+		len = XXV_MIN_PKT_SIZE;
+		ptr = txminframe;
+	}
+
 	/* Flush packet to main memory to be trasfered by DMA */
 	flush_cache((phys_addr_t)ptr, len);
 
@@ -632,7 +693,7 @@ static int axiemac_recv(struct udevice *dev, int flags, uchar **packetp)
 	temp = readl(&priv->dmarx->control);
 	temp &= ~XAXIDMA_IRQ_ALL_MASK;
 	writel(temp, &priv->dmarx->control);
-	if (!priv->eth_hasnobuf)
+	if (!priv->eth_hasnobuf  && priv->mactype == EMAC_1G)
 		length = rx_bd.app4 & 0xFFFF; /* max length mask */
 	else
 		length = rx_bd.status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
@@ -709,21 +770,25 @@ static int axi_emac_probe(struct udevice *dev)
 	priv->dmatx = plat->dmatx;
 	/* RX channel offset is 0x30 */
 	priv->dmarx = (struct axidma_reg *)((phys_addr_t)priv->dmatx + 0x30);
-	priv->eth_hasnobuf = plat->eth_hasnobuf;
-	priv->phyaddr = plat->phyaddr;
-	priv->phy_of_handle = plat->phy_of_handle;
-	priv->interface = pdata->phy_interface;
+	priv->mactype = plat->mactype;
+
+	if (priv->mactype == EMAC_1G) {
+		priv->eth_hasnobuf = plat->eth_hasnobuf;
+		priv->phyaddr = plat->phyaddr;
+		priv->phy_of_handle = plat->phy_of_handle;
+		priv->interface = pdata->phy_interface;
 
-	priv->bus = mdio_alloc();
-	priv->bus->read = axiemac_miiphy_read;
-	priv->bus->write = axiemac_miiphy_write;
-	priv->bus->priv = priv;
+		priv->bus = mdio_alloc();
+		priv->bus->read = axiemac_miiphy_read;
+		priv->bus->write = axiemac_miiphy_write;
+		priv->bus->priv = priv;
 
-	ret = mdio_register_seq(priv->bus, dev_seq(dev));
-	if (ret)
-		return ret;
+		ret = mdio_register_seq(priv->bus, dev_seq(dev));
+		if (ret)
+			return ret;
 
-	axiemac_phy_init(dev);
+		axiemac_phy_init(dev);
+	}
 
 	return 0;
 }
@@ -732,9 +797,11 @@ static int axi_emac_remove(struct udevice *dev)
 {
 	struct axidma_priv *priv = dev_get_priv(dev);
 
-	free(priv->phydev);
-	mdio_unregister(priv->bus);
-	mdio_free(priv->bus);
+	if (priv->mactype == EMAC_1G) {
+		free(priv->phydev);
+		mdio_unregister(priv->bus);
+		mdio_free(priv->bus);
+	}
 
 	return 0;
 }
@@ -757,6 +824,7 @@ static int axi_emac_of_to_plat(struct udevice *dev)
 	const char *phy_mode;
 
 	pdata->iobase = dev_read_addr(dev);
+	plat->mactype = dev_get_driver_data(dev);
 
 	offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
 				       "axistream-connected");
@@ -771,24 +839,29 @@ static int axi_emac_of_to_plat(struct udevice *dev)
 		return -EINVAL;
 	}
 
-	plat->phyaddr = -1;
+	if (plat->mactype == EMAC_1G) {
+		plat->phyaddr = -1;
 
-	offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy-handle");
-	if (offset > 0) {
-		plat->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
-		plat->phy_of_handle = offset;
-	}
+		offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
+					       "phy-handle");
+		if (offset > 0) {
+			plat->phyaddr = fdtdec_get_int(gd->fdt_blob, offset,
+						       "reg", -1);
+			plat->phy_of_handle = offset;
+		}
 
-	phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
-	if (phy_mode)
-		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
-	if (pdata->phy_interface == -1) {
-		printf("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
-		return -EINVAL;
-	}
+		phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
+		if (phy_mode)
+			pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+		if (pdata->phy_interface == -1) {
+			printf("%s: Invalid PHY interface '%s'\n", __func__,
+			       phy_mode);
+			return -EINVAL;
+		}
 
-	plat->eth_hasnobuf = fdtdec_get_bool(gd->fdt_blob, node,
-					     "xlnx,eth-hasnobuf");
+		plat->eth_hasnobuf = fdtdec_get_bool(gd->fdt_blob, node,
+						     "xlnx,eth-hasnobuf");
+	}
 
 	printf("AXI EMAC: %lx, phyaddr %d, interface %s\n", (ulong)pdata->iobase,
 	       plat->phyaddr, phy_string_for_interface(pdata->phy_interface));
@@ -797,7 +870,8 @@ static int axi_emac_of_to_plat(struct udevice *dev)
 }
 
 static const struct udevice_id axi_emac_ids[] = {
-	{ .compatible = "xlnx,axi-ethernet-1.00.a" },
+	{ .compatible = "xlnx,axi-ethernet-1.00.a", .data = (uintptr_t)EMAC_1G },
+	{ .compatible = "xlnx,xxv-ethernet-1.0", .data = (uintptr_t)EMAC_10G_25G },
 	{ }
 };
 
-- 
2.17.1

Re: [PATCH 1/2] net: xilinx: axi_emac: Cleanup of of_to_plat()

From: Ramon Fried <hidden>
Date: 2021-06-27 20:00:48

On Thu, Jun 24, 2021 at 9:35 AM Ashok Reddy Soma
[off-list ref] wrote:
quoted hunk
There are lot of accesses to priv data in of_to_plat(), which is incorrect.
Create a platform data structure and use it in of_to_plat(), then copy all
platform data to priv data in probe.

Signed-off-by: Ashok Reddy Soma <redacted>
---

 drivers/net/xilinx_axi_emac.c | 47 ++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 15 deletions(-)
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index 2ce6271afe..cfc6082475 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -87,6 +87,16 @@ struct axidma_reg {
        u32 tail_hi; /* TAILDESC high 32 bit */
 };

+/* Platform data structures */
+struct axidma_plat {
+       struct eth_pdata eth_pdata;
+       struct axidma_reg *dmatx;
+       struct axidma_reg *dmarx;
+       int phyaddr;
+       u8 eth_hasnobuf;
+       int phy_of_handle;
+};
+
 /* Private driver structures */
 struct axidma_priv {
        struct axidma_reg *dmatx;
@@ -690,9 +700,20 @@ static int axiemac_miiphy_write(struct mii_dev *bus, int addr, int devad,

 static int axi_emac_probe(struct udevice *dev)
 {
+       struct axidma_plat *plat = dev_get_plat(dev);
+       struct eth_pdata *pdata = &plat->eth_pdata;
        struct axidma_priv *priv = dev_get_priv(dev);
        int ret;

+       priv->iobase = (struct axi_regs *)pdata->iobase;
+       priv->dmatx = plat->dmatx;
+       /* RX channel offset is 0x30 */
+       priv->dmarx = (struct axidma_reg *)((phys_addr_t)priv->dmatx + 0x30);
+       priv->eth_hasnobuf = plat->eth_hasnobuf;
+       priv->phyaddr = plat->phyaddr;
+       priv->phy_of_handle = plat->phy_of_handle;
+       priv->interface = pdata->phy_interface;
+
        priv->bus = mdio_alloc();
        priv->bus->read = axiemac_miiphy_read;
        priv->bus->write = axiemac_miiphy_write;
@@ -729,14 +750,13 @@ static const struct eth_ops axi_emac_ops = {

 static int axi_emac_of_to_plat(struct udevice *dev)
 {
-       struct eth_pdata *pdata = dev_get_plat(dev);
-       struct axidma_priv *priv = dev_get_priv(dev);
+       struct axidma_plat *plat = dev_get_plat(dev);
+       struct eth_pdata *pdata = &plat->eth_pdata;
        int node = dev_of_offset(dev);
        int offset = 0;
        const char *phy_mode;

        pdata->iobase = dev_read_addr(dev);
-       priv->iobase = (struct axi_regs *)pdata->iobase;

        offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
                                       "axistream-connected");
@@ -744,21 +764,19 @@ static int axi_emac_of_to_plat(struct udevice *dev)
                printf("%s: axistream is not found\n", __func__);
                return -EINVAL;
        }
-       priv->dmatx = (struct axidma_reg *)fdtdec_get_addr(gd->fdt_blob,
+       plat->dmatx = (struct axidma_reg *)fdtdec_get_addr(gd->fdt_blob,
                                                          offset, "reg");
-       if (!priv->dmatx) {
+       if (!plat->dmatx) {
                printf("%s: axi_dma register space not found\n", __func__);
                return -EINVAL;
        }
-       /* RX channel offset is 0x30 */
-       priv->dmarx = (struct axidma_reg *)((phys_addr_t)priv->dmatx + 0x30);

-       priv->phyaddr = -1;
+       plat->phyaddr = -1;

        offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy-handle");
        if (offset > 0) {
-               priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
-               priv->phy_of_handle = offset;
+               plat->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
+               plat->phy_of_handle = offset;
        }

        phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
@@ -768,13 +786,12 @@ static int axi_emac_of_to_plat(struct udevice *dev)
                printf("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
                return -EINVAL;
        }
-       priv->interface = pdata->phy_interface;

-       priv->eth_hasnobuf = fdtdec_get_bool(gd->fdt_blob, node,
+       plat->eth_hasnobuf = fdtdec_get_bool(gd->fdt_blob, node,
                                             "xlnx,eth-hasnobuf");

-       printf("AXI EMAC: %lx, phyaddr %d, interface %s\n", (ulong)priv->iobase,
-              priv->phyaddr, phy_string_for_interface(priv->interface));
+       printf("AXI EMAC: %lx, phyaddr %d, interface %s\n", (ulong)pdata->iobase,
+              plat->phyaddr, phy_string_for_interface(pdata->phy_interface));

        return 0;
 }
@@ -793,5 +810,5 @@ U_BOOT_DRIVER(axi_emac) = {
        .remove = axi_emac_remove,
        .ops    = &axi_emac_ops,
        .priv_auto      = sizeof(struct axidma_priv),
-       .plat_auto      = sizeof(struct eth_pdata),
+       .plat_auto      = sizeof(struct axidma_plat),
 };
--
2.17.1
Reviewed-by: Ramon Fried <redacted>

Re: [PATCH 2/2] net: xilinx: axi_emac: Add support for 10G/25G AXI ethernet

From: Ramon Fried <hidden>
Date: 2021-06-27 20:01:46

On Thu, Jun 24, 2021 at 9:35 AM Ashok Reddy Soma
[off-list ref] wrote:
quoted hunk
Add support for 10G/25G (XXV) high speed ethernet. This Makes use of
the exiting AXI DMA, similar to 1G.

Signed-off-by: Alessandro Temil <redacted>
Signed-off-by: Ashok Reddy Soma <redacted>
---

 drivers/net/xilinx_axi_emac.c | 162 +++++++++++++++++++++++++---------
 1 file changed, 118 insertions(+), 44 deletions(-)
diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c
index cfc6082475..2ec76d0f52 100644
--- a/drivers/net/xilinx_axi_emac.c
+++ b/drivers/net/xilinx_axi_emac.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
+ * Copyright (C) 2021 Waymo LLC
  * Copyright (C) 2011 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2011 PetaLogix
  * Copyright (C) 2010 Xilinx, Inc. All rights reserved.
@@ -73,9 +74,22 @@ DECLARE_GLOBAL_DATA_PTR;
 #define XAXIDMA_BD_CTRL_TXSOF_MASK     0x08000000 /* First tx packet */
 #define XAXIDMA_BD_CTRL_TXEOF_MASK     0x04000000 /* Last tx packet */

-#define DMAALIGN       128
+/* Bitmasks for XXV Ethernet MAC */
+#define XXV_TC_TX_MASK         0x00000001
+#define XXV_TC_FCS_MASK                0x00000002
+#define XXV_RCW1_RX_MASK       0x00000001
+#define XXV_RCW1_FCS_MASK      0x00000002
+
+#define DMAALIGN               128
+#define XXV_MIN_PKT_SIZE       60

 static u8 rxframe[PKTSIZE_ALIGN] __attribute((aligned(DMAALIGN)));
+static u8 txminframe[XXV_MIN_PKT_SIZE] __attribute((aligned(DMAALIGN)));
+
+enum emac_variant {
+       EMAC_1G = 0,
+       EMAC_10G_25G = 1,
+};

 /* Reflect dma offsets */
 struct axidma_reg {
@@ -95,6 +109,7 @@ struct axidma_plat {
        int phyaddr;
        u8 eth_hasnobuf;
        int phy_of_handle;
+       enum emac_variant mactype;
 };

 /* Private driver structures */
@@ -108,6 +123,7 @@ struct axidma_priv {
        struct mii_dev *bus;
        u8 eth_hasnobuf;
        int phy_of_handle;
+       enum emac_variant mactype;
 };

 /* BD descriptors */
@@ -154,6 +170,14 @@ struct axi_regs {
        u32 uaw1; /* 0x704: Unicast address word 1 */
 };

+struct xxv_axi_regs {
+       u32 gt_reset;   /* 0x0 */
+       u32 reserved[2];
+       u32 tc;         /* 0xC: Tx Configuration */
+       u32 reserved2;
+       u32 rcw1;       /* 0x14: Rx Configuration Word 1 */
+};
+
 /* Use MII register 1 (MII status register) to detect PHY */
 #define PHY_DETECT_REG  1
@@ -385,6 +409,18 @@ static void axiemac_stop(struct udevice *dev)
        debug("axiemac: Halted\n");
 }

+static int xxv_axi_ethernet_init(struct axidma_priv *priv)
+{
+       struct xxv_axi_regs *regs = (struct xxv_axi_regs *)priv->iobase;
+
+       writel(readl(&regs->rcw1) | XXV_RCW1_FCS_MASK, &regs->rcw1);
+       writel(readl(&regs->tc) | XXV_TC_FCS_MASK, &regs->tc);
+       writel(readl(&regs->tc) | XXV_TC_TX_MASK, &regs->tc);
+       writel(readl(&regs->rcw1) | XXV_RCW1_RX_MASK, &regs->rcw1);
+
+       return 0;
+}
+
 static int axi_ethernet_init(struct axidma_priv *priv)
 {
        struct axi_regs *regs = priv->iobase;
@@ -440,6 +476,9 @@ static int axiemac_write_hwaddr(struct udevice *dev)
        struct axidma_priv *priv = dev_get_priv(dev);
        struct axi_regs *regs = priv->iobase;

+       if (priv->mactype != EMAC_1G)
+               return 0;
+
        /* Set the MAC address */
        int val = ((pdata->enetaddr[3] << 24) | (pdata->enetaddr[2] << 16) |
                (pdata->enetaddr[1] << 8) | (pdata->enetaddr[0]));
@@ -477,7 +516,6 @@ static void axi_dma_init(struct axidma_priv *priv)
 static int axiemac_start(struct udevice *dev)
 {
        struct axidma_priv *priv = dev_get_priv(dev);
-       struct axi_regs *regs = priv->iobase;
        u32 temp;

        debug("axiemac: Init started\n");
@@ -490,8 +528,13 @@ static int axiemac_start(struct udevice *dev)
        axi_dma_init(priv);

        /* Initialize AxiEthernet hardware. */
-       if (axi_ethernet_init(priv))
-               return -1;
+       if (priv->mactype == EMAC_1G) {
+               if (axi_ethernet_init(priv))
+                       return -1;
+       } else {
+               if (xxv_axi_ethernet_init(priv))
+                       return -1;
+       }

        /* Disable all RX interrupts before RxBD space setup */
        temp = readl(&priv->dmarx->control);
@@ -525,15 +568,25 @@ static int axiemac_start(struct udevice *dev)
        /* Rx BD is ready - start */
        axienet_dma_write(&rx_bd, &priv->dmarx->tail);

-       /* Enable TX */
-       writel(XAE_TC_TX_MASK, &regs->tc);
-       /* Enable RX */
-       writel(XAE_RCW1_RX_MASK, &regs->rcw1);
+       if (priv->mactype == EMAC_1G) {
+               struct axi_regs *regs = priv->iobase;
+               /* Enable TX */
+               writel(XAE_TC_TX_MASK, &regs->tc);
+               /* Enable RX */
+               writel(XAE_RCW1_RX_MASK, &regs->rcw1);
+
+               /* PHY setup */
+               if (!setup_phy(dev)) {
+                       axiemac_stop(dev);
+                       return -1;
+               }
+       } else {
+               struct xxv_axi_regs *regs = (struct xxv_axi_regs *)priv->iobase;
+               /* Enable TX */
+               writel(readl(&regs->tc) | XXV_TC_TX_MASK, &regs->tc);

-       /* PHY setup */
-       if (!setup_phy(dev)) {
-               axiemac_stop(dev);
-               return -1;
+               /* Enable RX */
+               writel(readl(&regs->rcw1) | XXV_RCW1_RX_MASK, &regs->rcw1);
        }

        debug("axiemac: Init complete\n");
@@ -548,6 +601,14 @@ static int axiemac_send(struct udevice *dev, void *ptr, int len)
        if (len > PKTSIZE_ALIGN)
                len = PKTSIZE_ALIGN;

+       /* If size is less than min packet size, pad to min size */
+       if (priv->mactype == EMAC_10G_25G && len < XXV_MIN_PKT_SIZE) {
+               memset(txminframe, 0, XXV_MIN_PKT_SIZE);
+               memcpy(txminframe, ptr, len);
+               len = XXV_MIN_PKT_SIZE;
+               ptr = txminframe;
+       }
+
        /* Flush packet to main memory to be trasfered by DMA */
        flush_cache((phys_addr_t)ptr, len);
@@ -632,7 +693,7 @@ static int axiemac_recv(struct udevice *dev, int flags, uchar **packetp)
        temp = readl(&priv->dmarx->control);
        temp &= ~XAXIDMA_IRQ_ALL_MASK;
        writel(temp, &priv->dmarx->control);
-       if (!priv->eth_hasnobuf)
+       if (!priv->eth_hasnobuf  && priv->mactype == EMAC_1G)
                length = rx_bd.app4 & 0xFFFF; /* max length mask */
        else
                length = rx_bd.status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
@@ -709,21 +770,25 @@ static int axi_emac_probe(struct udevice *dev)
        priv->dmatx = plat->dmatx;
        /* RX channel offset is 0x30 */
        priv->dmarx = (struct axidma_reg *)((phys_addr_t)priv->dmatx + 0x30);
-       priv->eth_hasnobuf = plat->eth_hasnobuf;
-       priv->phyaddr = plat->phyaddr;
-       priv->phy_of_handle = plat->phy_of_handle;
-       priv->interface = pdata->phy_interface;
+       priv->mactype = plat->mactype;
+
+       if (priv->mactype == EMAC_1G) {
+               priv->eth_hasnobuf = plat->eth_hasnobuf;
+               priv->phyaddr = plat->phyaddr;
+               priv->phy_of_handle = plat->phy_of_handle;
+               priv->interface = pdata->phy_interface;

-       priv->bus = mdio_alloc();
-       priv->bus->read = axiemac_miiphy_read;
-       priv->bus->write = axiemac_miiphy_write;
-       priv->bus->priv = priv;
+               priv->bus = mdio_alloc();
+               priv->bus->read = axiemac_miiphy_read;
+               priv->bus->write = axiemac_miiphy_write;
+               priv->bus->priv = priv;

-       ret = mdio_register_seq(priv->bus, dev_seq(dev));
-       if (ret)
-               return ret;
+               ret = mdio_register_seq(priv->bus, dev_seq(dev));
+               if (ret)
+                       return ret;

-       axiemac_phy_init(dev);
+               axiemac_phy_init(dev);
+       }

        return 0;
 }
@@ -732,9 +797,11 @@ static int axi_emac_remove(struct udevice *dev)
 {
        struct axidma_priv *priv = dev_get_priv(dev);

-       free(priv->phydev);
-       mdio_unregister(priv->bus);
-       mdio_free(priv->bus);
+       if (priv->mactype == EMAC_1G) {
+               free(priv->phydev);
+               mdio_unregister(priv->bus);
+               mdio_free(priv->bus);
+       }

        return 0;
 }
@@ -757,6 +824,7 @@ static int axi_emac_of_to_plat(struct udevice *dev)
        const char *phy_mode;

        pdata->iobase = dev_read_addr(dev);
+       plat->mactype = dev_get_driver_data(dev);

        offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
                                       "axistream-connected");
@@ -771,24 +839,29 @@ static int axi_emac_of_to_plat(struct udevice *dev)
                return -EINVAL;
        }

-       plat->phyaddr = -1;
+       if (plat->mactype == EMAC_1G) {
+               plat->phyaddr = -1;

-       offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy-handle");
-       if (offset > 0) {
-               plat->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
-               plat->phy_of_handle = offset;
-       }
+               offset = fdtdec_lookup_phandle(gd->fdt_blob, node,
+                                              "phy-handle");
+               if (offset > 0) {
+                       plat->phyaddr = fdtdec_get_int(gd->fdt_blob, offset,
+                                                      "reg", -1);
+                       plat->phy_of_handle = offset;
+               }

-       phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
-       if (phy_mode)
-               pdata->phy_interface = phy_get_interface_by_name(phy_mode);
-       if (pdata->phy_interface == -1) {
-               printf("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
-               return -EINVAL;
-       }
+               phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL);
+               if (phy_mode)
+                       pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+               if (pdata->phy_interface == -1) {
+                       printf("%s: Invalid PHY interface '%s'\n", __func__,
+                              phy_mode);
+                       return -EINVAL;
+               }

-       plat->eth_hasnobuf = fdtdec_get_bool(gd->fdt_blob, node,
-                                            "xlnx,eth-hasnobuf");
+               plat->eth_hasnobuf = fdtdec_get_bool(gd->fdt_blob, node,
+                                                    "xlnx,eth-hasnobuf");
+       }

        printf("AXI EMAC: %lx, phyaddr %d, interface %s\n", (ulong)pdata->iobase,
               plat->phyaddr, phy_string_for_interface(pdata->phy_interface));
@@ -797,7 +870,8 @@ static int axi_emac_of_to_plat(struct udevice *dev)
 }

 static const struct udevice_id axi_emac_ids[] = {
-       { .compatible = "xlnx,axi-ethernet-1.00.a" },
+       { .compatible = "xlnx,axi-ethernet-1.00.a", .data = (uintptr_t)EMAC_1G },
+       { .compatible = "xlnx,xxv-ethernet-1.0", .data = (uintptr_t)EMAC_10G_25G },
        { }
 };

--
2.17.1
Reviewed-by: Ramon Fried <redacted>

Re: [PATCH 0/2] Add support for 10G/25G to AXI emac driver

From: Michal Simek <hidden>
Date: 2021-06-28 07:08:05


On 6/24/21 8:34 AM, Ashok Reddy Soma wrote:
 - Cleanup of_to_plat() to access platform data only in it
 - Copy plat data to priv data in probe function
 - Add support for 10G/25G to the AXI emac driver
 - Keep all phy related activity in the driver for 1G only


Ashok Reddy Soma (2):
  net: xilinx: axi_emac: Cleanup of of_to_plat()
  net: xilinx: axi_emac: Add support for 10G/25G AXI ethernet

 drivers/net/xilinx_axi_emac.c | 193 +++++++++++++++++++++++++---------
 1 file changed, 142 insertions(+), 51 deletions(-)
Applied.
M

Re: [PATCH 0/2] Add support for 10G/25G to AXI emac driver

From: Ramon Fried <hidden>
Date: 2021-06-28 17:13:38

On Mon, Jun 28, 2021 at 10:07 AM Michal Simek [off-list ref] wrote:


On 6/24/21 8:34 AM, Ashok Reddy Soma wrote:
quoted
 - Cleanup of_to_plat() to access platform data only in it
 - Copy plat data to priv data in probe function
 - Add support for 10G/25G to the AXI emac driver
 - Keep all phy related activity in the driver for 1G only


Ashok Reddy Soma (2):
  net: xilinx: axi_emac: Cleanup of of_to_plat()
  net: xilinx: axi_emac: Add support for 10G/25G AXI ethernet

 drivers/net/xilinx_axi_emac.c | 193 +++++++++++++++++++++++++---------
 1 file changed, 142 insertions(+), 51 deletions(-)
Applied.
Michal, did you apply V2 with Simon's remarks ?

RE: [PATCH 0/2] Add support for 10G/25G to AXI emac driver

From: Ashok Reddy Soma <hidden>
Date: 2021-06-29 04:30:55

-----Original Message-----
From: Ramon Fried <redacted>
Sent: Monday, June 28, 2021 10:43 PM
To: Michal Simek <redacted>; Simon Glass <sjg@chromium.org>
Cc: Ashok Reddy Soma <redacted>; U-Boot Mailing List <u-
boot@lists.denx.de>; Joe Hershberger [off-list ref]; Michal
Simek [off-list ref]; git [off-list ref];
somaashokreddy@gmail.com
Subject: Re: [PATCH 0/2] Add support for 10G/25G to AXI emac driver

On Mon, Jun 28, 2021 at 10:07 AM Michal Simek [off-list ref]
wrote:
quoted


On 6/24/21 8:34 AM, Ashok Reddy Soma wrote:
quoted
 - Cleanup of_to_plat() to access platform data only in it
 - Copy plat data to priv data in probe function
 - Add support for 10G/25G to the AXI emac driver
 - Keep all phy related activity in the driver for 1G only


Ashok Reddy Soma (2):
  net: xilinx: axi_emac: Cleanup of of_to_plat()
  net: xilinx: axi_emac: Add support for 10G/25G AXI ethernet

 drivers/net/xilinx_axi_emac.c | 193 +++++++++++++++++++++++++---------
 1 file changed, 142 insertions(+), 51 deletions(-)
Applied.
Michal, did you apply V2 with Simon's remarks ?
Hi Ramon,

This patch series is to support 10G/25G using AXI DMA. This support has been added to existing AXI emac driver.
This is not MRMAC driver, which I have added as a new driver(For which I am yet to send V2 with Simon comments addressed).

Thanks,
Ashok

Re: [PATCH 0/2] Add support for 10G/25G to AXI emac driver

From: Ramon Fried <hidden>
Date: 2021-06-29 05:17:33

On Tue, Jun 29, 2021 at 7:30 AM Ashok Reddy Soma [off-list ref] wrote:

quoted
-----Original Message-----
From: Ramon Fried <redacted>
Sent: Monday, June 28, 2021 10:43 PM
To: Michal Simek <redacted>; Simon Glass <sjg@chromium.org>
Cc: Ashok Reddy Soma <redacted>; U-Boot Mailing List <u-
boot@lists.denx.de>; Joe Hershberger [off-list ref]; Michal
Simek [off-list ref]; git [off-list ref];
somaashokreddy@gmail.com
Subject: Re: [PATCH 0/2] Add support for 10G/25G to AXI emac driver

On Mon, Jun 28, 2021 at 10:07 AM Michal Simek [off-list ref]
wrote:
quoted


On 6/24/21 8:34 AM, Ashok Reddy Soma wrote:
quoted
 - Cleanup of_to_plat() to access platform data only in it
 - Copy plat data to priv data in probe function
 - Add support for 10G/25G to the AXI emac driver
 - Keep all phy related activity in the driver for 1G only


Ashok Reddy Soma (2):
  net: xilinx: axi_emac: Cleanup of of_to_plat()
  net: xilinx: axi_emac: Add support for 10G/25G AXI ethernet

 drivers/net/xilinx_axi_emac.c | 193 +++++++++++++++++++++++++---------
 1 file changed, 142 insertions(+), 51 deletions(-)
Applied.
Michal, did you apply V2 with Simon's remarks ?
Hi Ramon,

This patch series is to support 10G/25G using AXI DMA. This support has been added to existing AXI emac driver.
This is not MRMAC driver, which I have added as a new driver(For which I am yet to send V2 with Simon comments addressed).

Thanks,
Ashok
Thanks Ashok, my bad.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help