Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc1b7c13 authored by Iyappan Subramanian's avatar Iyappan Subramanian Committed by David S. Miller
Browse files

drivers: net: xgene: Add 10GbE support with ring manager v2

parent ed9b7da0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ enum xgene_enet_rm {

#define BLOCK_ETH_CSR_OFFSET		0x2000
#define BLOCK_ETH_RING_IF_OFFSET	0x9000
#define BLOCK_ETH_CLKRST_CSR_OFFSET	0xc000
#define BLOCK_ETH_DIAG_CSR_OFFSET	0xD000

#define BLOCK_ETH_MAC_OFFSET		0x0000
+117 −24
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@
#define RES_RING_CSR	1
#define RES_RING_CMD	2

static const struct of_device_id xgene_enet_of_match[];

static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
{
	struct xgene_enet_raw_desc16 *raw_desc;
@@ -632,6 +634,25 @@ static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
	}
}

static bool is_irq_mbox_required(struct xgene_enet_pdata *pdata,
				 struct xgene_enet_desc_ring *ring)
{
	if ((pdata->enet_id == XGENE_ENET2) &&
	    (xgene_enet_ring_owner(ring->id) == RING_OWNER_CPU)) {
		return true;
	}

	return false;
}

static void __iomem *xgene_enet_ring_cmd_base(struct xgene_enet_pdata *pdata,
					      struct xgene_enet_desc_ring *ring)
{
	u8 num_ring_id_shift = pdata->ring_ops->num_ring_id_shift;

	return pdata->ring_cmd_addr + (ring->num << num_ring_id_shift);
}

static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
			struct net_device *ndev, u32 ring_num,
			enum xgene_enet_ring_cfgsize cfgsize, u32 ring_id)
@@ -663,7 +684,18 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
	}
	ring->size = size;

	ring->cmd_base = pdata->ring_cmd_addr + (ring->num << 6);
	if (is_irq_mbox_required(pdata, ring)) {
		ring->irq_mbox_addr = dma_zalloc_coherent(dev, INTR_MBOX_SIZE,
				&ring->irq_mbox_dma, GFP_KERNEL);
		if (!ring->irq_mbox_addr) {
			dma_free_coherent(dev, size, ring->desc_addr,
					  ring->dma);
			devm_kfree(dev, ring);
			return NULL;
		}
	}

	ring->cmd_base = xgene_enet_ring_cmd_base(pdata, ring);
	ring->cmd = ring->cmd_base + INC_DEC_CMD_ADDR;
	ring = pdata->ring_ops->setup(ring);
	netdev_dbg(ndev, "ring info: num=%d  size=%d  id=%d  slots=%d\n",
@@ -677,12 +709,34 @@ static u16 xgene_enet_get_ring_id(enum xgene_ring_owner owner, u8 bufnum)
	return (owner << 6) | (bufnum & GENMASK(5, 0));
}

static enum xgene_ring_owner xgene_derive_ring_owner(struct xgene_enet_pdata *p)
{
	enum xgene_ring_owner owner;

	if (p->enet_id == XGENE_ENET1) {
		switch (p->phy_mode) {
		case PHY_INTERFACE_MODE_SGMII:
			owner = RING_OWNER_ETH0;
			break;
		default:
			owner = (!p->port_id) ? RING_OWNER_ETH0 :
						RING_OWNER_ETH1;
			break;
		}
	} else {
		owner = (!p->port_id) ? RING_OWNER_ETH0 : RING_OWNER_ETH1;
	}

	return owner;
}

static int xgene_enet_create_desc_rings(struct net_device *ndev)
{
	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
	struct device *dev = ndev_to_dev(ndev);
	struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring;
	struct xgene_enet_desc_ring *buf_pool = NULL;
	enum xgene_ring_owner owner;
	u8 cpu_bufnum = pdata->cpu_bufnum;
	u8 eth_bufnum = pdata->eth_bufnum;
	u8 bp_bufnum = pdata->bp_bufnum;
@@ -691,6 +745,7 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
	int ret;

	/* allocate rx descriptor ring */
	owner = xgene_derive_ring_owner(pdata);
	ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++);
	rx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
					      RING_CFGSIZE_16KB, ring_id);
@@ -700,7 +755,8 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
	}

	/* allocate buffer pool for receiving packets */
	ring_id = xgene_enet_get_ring_id(RING_OWNER_ETH0, bp_bufnum++);
	owner = xgene_derive_ring_owner(pdata);
	ring_id = xgene_enet_get_ring_id(owner, bp_bufnum++);
	buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
					       RING_CFGSIZE_2KB, ring_id);
	if (!buf_pool) {
@@ -729,7 +785,8 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
	pdata->rx_ring = rx_ring;

	/* allocate tx descriptor ring */
	ring_id = xgene_enet_get_ring_id(RING_OWNER_ETH0, eth_bufnum++);
	owner = xgene_derive_ring_owner(pdata);
	ring_id = xgene_enet_get_ring_id(owner, eth_bufnum++);
	tx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
					      RING_CFGSIZE_16KB, ring_id);
	if (!tx_ring) {
@@ -957,7 +1014,10 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
		pdata->clk = NULL;
	}

	if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
		base_addr = pdata->base_addr - (pdata->port_id * MAC_OFFSET);
	else
		base_addr = pdata->base_addr;
	pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
	pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET;
	pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET;
@@ -1029,6 +1089,7 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
		break;
	}

	if (pdata->enet_id == XGENE_ENET1) {
		switch (pdata->port_id) {
		case 0:
			pdata->cpu_bufnum = START_CPU_BUFNUM_0;
@@ -1045,8 +1106,27 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
		default:
			break;
		}

		pdata->ring_ops = &xgene_ring1_ops;
	} else {
		switch (pdata->port_id) {
		case 0:
			pdata->cpu_bufnum = X2_START_CPU_BUFNUM_0;
			pdata->eth_bufnum = X2_START_ETH_BUFNUM_0;
			pdata->bp_bufnum = X2_START_BP_BUFNUM_0;
			pdata->ring_num = X2_START_RING_NUM_0;
			break;
		case 1:
			pdata->cpu_bufnum = X2_START_CPU_BUFNUM_1;
			pdata->eth_bufnum = X2_START_ETH_BUFNUM_1;
			pdata->bp_bufnum = X2_START_BP_BUFNUM_1;
			pdata->ring_num = X2_START_RING_NUM_1;
			break;
		default:
			break;
		}
		pdata->rm = RM0;
		pdata->ring_ops = &xgene_ring2_ops;
	}
}

static void xgene_enet_napi_add(struct xgene_enet_pdata *pdata)
@@ -1082,6 +1162,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
	struct xgene_enet_pdata *pdata;
	struct device *dev = &pdev->dev;
	struct xgene_mac_ops *mac_ops;
	const struct of_device_id *of_id;
	int ret;

	ndev = alloc_etherdev(sizeof(struct xgene_enet_pdata));
@@ -1100,6 +1181,17 @@ static int xgene_enet_probe(struct platform_device *pdev)
			  NETIF_F_GSO |
			  NETIF_F_GRO;

#ifdef CONFIG_OF
	of_id = of_match_device(xgene_enet_of_match, &pdev->dev);
	if (of_id) {
		pdata->enet_id = (enum xgene_enet_id)of_id->data;
		if (!pdata->enet_id) {
			free_netdev(ndev);
			return -ENODEV;
		}
	}
#endif

	ret = xgene_enet_get_resources(pdata);
	if (ret)
		goto err;
@@ -1171,9 +1263,10 @@ MODULE_DEVICE_TABLE(acpi, xgene_enet_acpi_match);

#ifdef CONFIG_OF
static const struct of_device_id xgene_enet_of_match[] = {
	{.compatible = "apm,xgene-enet",},
	{.compatible = "apm,xgene1-sgenet",},
	{.compatible = "apm,xgene1-xgenet",},
	{.compatible = "apm,xgene-enet",    .data = (void *)XGENE_ENET1},
	{.compatible = "apm,xgene1-sgenet", .data = (void *)XGENE_ENET1},
	{.compatible = "apm,xgene1-xgenet", .data = (void *)XGENE_ENET1},
	{.compatible = "apm,xgene2-xgenet", .data = (void *)XGENE_ENET2},
	{},
};

+17 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include <linux/if_vlan.h>
#include <linux/phy.h>
#include "xgene_enet_hw.h"
#include "xgene_enet_ring2.h"

#define XGENE_DRV_VERSION	"v1.0"
#define XGENE_ENET_MAX_MTU	1536
@@ -51,12 +52,27 @@
#define START_BP_BUFNUM_1	0x2A
#define START_RING_NUM_1	264

#define X2_START_CPU_BUFNUM_0	0
#define X2_START_ETH_BUFNUM_0	0
#define X2_START_BP_BUFNUM_0	0x20
#define X2_START_RING_NUM_0	0

#define X2_START_CPU_BUFNUM_1	0xc
#define X2_START_ETH_BUFNUM_1	0
#define X2_START_BP_BUFNUM_1	0x20
#define X2_START_RING_NUM_1	256

#define IRQ_ID_SIZE		16
#define XGENE_MAX_TXC_RINGS	1

#define PHY_POLL_LINK_ON	(10 * HZ)
#define PHY_POLL_LINK_OFF	(PHY_POLL_LINK_ON / 5)

enum xgene_enet_id {
	XGENE_ENET1 = 1,
	XGENE_ENET2
};

/* software context of a descriptor ring */
struct xgene_enet_desc_ring {
	struct net_device *ndev;
@@ -124,6 +140,7 @@ struct xgene_enet_pdata {
	int phy_speed;
	struct clk *clk;
	struct platform_device *pdev;
	enum xgene_enet_id enet_id;
	struct xgene_enet_desc_ring *tx_ring;
	struct xgene_enet_desc_ring *rx_ring;
	char *dev_name;
+0 −1
Original line number Diff line number Diff line
@@ -122,7 +122,6 @@ static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,

	return true;
}

static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata,
			      u32 rd_addr, u32 *rd_data)
{
+17 −0
Original line number Diff line number Diff line
@@ -24,6 +24,23 @@
#define BLOCK_AXG_MAC_OFFSET		0x0800
#define BLOCK_AXG_MAC_CSR_OFFSET	0x2000

#define XGENET_SRST_ADDR		0x0000
#define XGENET_CLKEN_ADDR		0x0008

#define CSR_CLK		BIT(0)
#define XGENET_CLK	BIT(1)
#define PCS_CLK		BIT(3)
#define AN_REF_CLK	BIT(4)
#define AN_CLK		BIT(5)
#define AD_CLK		BIT(6)

#define CSR_RST		BIT(0)
#define XGENET_RST	BIT(1)
#define PCS_RST		BIT(3)
#define AN_REF_RST	BIT(4)
#define AN_RST		BIT(5)
#define AD_RST		BIT(6)

#define AXGMAC_CONFIG_0			0x0000
#define AXGMAC_CONFIG_1			0x0004
#define HSTMACRST			BIT(31)