All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
To: <u-boot@lists.denx.de>
Cc: <joe.hershberger@ni.com>, <rfried.dev@gmail.com>,
	<monstr@monstr.eu>, <git@xilinx.com>, <somaashokreddy@gmail.com>,
	Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>,
	Alessandro Temil <atemil@waymo.com>
Subject: [PATCH 2/2] net: xilinx: axi_emac: Add support for 10G/25G AXI ethernet
Date: Thu, 24 Jun 2021 00:34:41 -0600	[thread overview]
Message-ID: <20210624063441.24072-3-ashok.reddy.soma@xilinx.com> (raw)
In-Reply-To: <20210624063441.24072-1-ashok.reddy.soma@xilinx.com>

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 <atemil@waymo.com>
Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
---

 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


  parent reply	other threads:[~2021-06-24  6:35 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-24  6:34 [PATCH 0/2] Add support for 10G/25G to AXI emac driver Ashok Reddy Soma
2021-06-24  6:34 ` [PATCH 1/2] net: xilinx: axi_emac: Cleanup of of_to_plat() Ashok Reddy Soma
2021-06-27 20:00   ` Ramon Fried
2021-06-24  6:34 ` Ashok Reddy Soma [this message]
2021-06-27 20:01   ` [PATCH 2/2] net: xilinx: axi_emac: Add support for 10G/25G AXI ethernet Ramon Fried
2021-06-28  7:07 ` [PATCH 0/2] Add support for 10G/25G to AXI emac driver Michal Simek
2021-06-28 17:13   ` Ramon Fried
2021-06-29  4:30     ` Ashok Reddy Soma
2021-06-29  5:17       ` Ramon Fried

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210624063441.24072-3-ashok.reddy.soma@xilinx.com \
    --to=ashok.reddy.soma@xilinx.com \
    --cc=atemil@waymo.com \
    --cc=git@xilinx.com \
    --cc=joe.hershberger@ni.com \
    --cc=monstr@monstr.eu \
    --cc=rfried.dev@gmail.com \
    --cc=somaashokreddy@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.