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

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

Signed-off-by: default avatarIyappan Subramanian <isubramanian@apm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ed9b7da0
...@@ -102,6 +102,7 @@ enum xgene_enet_rm { ...@@ -102,6 +102,7 @@ enum xgene_enet_rm {
#define BLOCK_ETH_CSR_OFFSET 0x2000 #define BLOCK_ETH_CSR_OFFSET 0x2000
#define BLOCK_ETH_RING_IF_OFFSET 0x9000 #define BLOCK_ETH_RING_IF_OFFSET 0x9000
#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xc000
#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000 #define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000
#define BLOCK_ETH_MAC_OFFSET 0x0000 #define BLOCK_ETH_MAC_OFFSET 0x0000
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#define RES_RING_CSR 1 #define RES_RING_CSR 1
#define RES_RING_CMD 2 #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) static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool)
{ {
struct xgene_enet_raw_desc16 *raw_desc; struct xgene_enet_raw_desc16 *raw_desc;
...@@ -632,6 +634,25 @@ static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata) ...@@ -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( static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
struct net_device *ndev, u32 ring_num, struct net_device *ndev, u32 ring_num,
enum xgene_enet_ring_cfgsize cfgsize, u32 ring_id) enum xgene_enet_ring_cfgsize cfgsize, u32 ring_id)
...@@ -663,7 +684,18 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring( ...@@ -663,7 +684,18 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring(
} }
ring->size = size; 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->cmd = ring->cmd_base + INC_DEC_CMD_ADDR;
ring = pdata->ring_ops->setup(ring); ring = pdata->ring_ops->setup(ring);
netdev_dbg(ndev, "ring info: num=%d size=%d id=%d slots=%d\n", 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) ...@@ -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)); 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) static int xgene_enet_create_desc_rings(struct net_device *ndev)
{ {
struct xgene_enet_pdata *pdata = netdev_priv(ndev); struct xgene_enet_pdata *pdata = netdev_priv(ndev);
struct device *dev = ndev_to_dev(ndev); struct device *dev = ndev_to_dev(ndev);
struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring; struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring;
struct xgene_enet_desc_ring *buf_pool = NULL; struct xgene_enet_desc_ring *buf_pool = NULL;
enum xgene_ring_owner owner;
u8 cpu_bufnum = pdata->cpu_bufnum; u8 cpu_bufnum = pdata->cpu_bufnum;
u8 eth_bufnum = pdata->eth_bufnum; u8 eth_bufnum = pdata->eth_bufnum;
u8 bp_bufnum = pdata->bp_bufnum; u8 bp_bufnum = pdata->bp_bufnum;
...@@ -691,6 +745,7 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev) ...@@ -691,6 +745,7 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
int ret; int ret;
/* allocate rx descriptor ring */ /* allocate rx descriptor ring */
owner = xgene_derive_ring_owner(pdata);
ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++); ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++);
rx_ring = xgene_enet_create_desc_ring(ndev, ring_num++, rx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
RING_CFGSIZE_16KB, ring_id); RING_CFGSIZE_16KB, ring_id);
...@@ -700,7 +755,8 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev) ...@@ -700,7 +755,8 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
} }
/* allocate buffer pool for receiving packets */ /* 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++, buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
RING_CFGSIZE_2KB, ring_id); RING_CFGSIZE_2KB, ring_id);
if (!buf_pool) { if (!buf_pool) {
...@@ -729,7 +785,8 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev) ...@@ -729,7 +785,8 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
pdata->rx_ring = rx_ring; pdata->rx_ring = rx_ring;
/* allocate tx descriptor 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++, tx_ring = xgene_enet_create_desc_ring(ndev, ring_num++,
RING_CFGSIZE_16KB, ring_id); RING_CFGSIZE_16KB, ring_id);
if (!tx_ring) { if (!tx_ring) {
...@@ -957,7 +1014,10 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) ...@@ -957,7 +1014,10 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
pdata->clk = NULL; pdata->clk = NULL;
} }
if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
base_addr = pdata->base_addr - (pdata->port_id * MAC_OFFSET); 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_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET;
pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_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; 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) ...@@ -1029,6 +1089,7 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
break; break;
} }
if (pdata->enet_id == XGENE_ENET1) {
switch (pdata->port_id) { switch (pdata->port_id) {
case 0: case 0:
pdata->cpu_bufnum = START_CPU_BUFNUM_0; pdata->cpu_bufnum = START_CPU_BUFNUM_0;
...@@ -1045,8 +1106,27 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata) ...@@ -1045,8 +1106,27 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
default: default:
break; break;
} }
pdata->ring_ops = &xgene_ring1_ops; 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) static void xgene_enet_napi_add(struct xgene_enet_pdata *pdata)
...@@ -1082,6 +1162,7 @@ static int xgene_enet_probe(struct platform_device *pdev) ...@@ -1082,6 +1162,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
struct xgene_enet_pdata *pdata; struct xgene_enet_pdata *pdata;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct xgene_mac_ops *mac_ops; struct xgene_mac_ops *mac_ops;
const struct of_device_id *of_id;
int ret; int ret;
ndev = alloc_etherdev(sizeof(struct xgene_enet_pdata)); ndev = alloc_etherdev(sizeof(struct xgene_enet_pdata));
...@@ -1100,6 +1181,17 @@ static int xgene_enet_probe(struct platform_device *pdev) ...@@ -1100,6 +1181,17 @@ static int xgene_enet_probe(struct platform_device *pdev)
NETIF_F_GSO | NETIF_F_GSO |
NETIF_F_GRO; 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); ret = xgene_enet_get_resources(pdata);
if (ret) if (ret)
goto err; goto err;
...@@ -1171,9 +1263,10 @@ MODULE_DEVICE_TABLE(acpi, xgene_enet_acpi_match); ...@@ -1171,9 +1263,10 @@ MODULE_DEVICE_TABLE(acpi, xgene_enet_acpi_match);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id xgene_enet_of_match[] = { static const struct of_device_id xgene_enet_of_match[] = {
{.compatible = "apm,xgene-enet",}, {.compatible = "apm,xgene-enet", .data = (void *)XGENE_ENET1},
{.compatible = "apm,xgene1-sgenet",}, {.compatible = "apm,xgene1-sgenet", .data = (void *)XGENE_ENET1},
{.compatible = "apm,xgene1-xgenet",}, {.compatible = "apm,xgene1-xgenet", .data = (void *)XGENE_ENET1},
{.compatible = "apm,xgene2-xgenet", .data = (void *)XGENE_ENET2},
{}, {},
}; };
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/phy.h> #include <linux/phy.h>
#include "xgene_enet_hw.h" #include "xgene_enet_hw.h"
#include "xgene_enet_ring2.h"
#define XGENE_DRV_VERSION "v1.0" #define XGENE_DRV_VERSION "v1.0"
#define XGENE_ENET_MAX_MTU 1536 #define XGENE_ENET_MAX_MTU 1536
...@@ -51,12 +52,27 @@ ...@@ -51,12 +52,27 @@
#define START_BP_BUFNUM_1 0x2A #define START_BP_BUFNUM_1 0x2A
#define START_RING_NUM_1 264 #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 IRQ_ID_SIZE 16
#define XGENE_MAX_TXC_RINGS 1 #define XGENE_MAX_TXC_RINGS 1
#define PHY_POLL_LINK_ON (10 * HZ) #define PHY_POLL_LINK_ON (10 * HZ)
#define PHY_POLL_LINK_OFF (PHY_POLL_LINK_ON / 5) #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 */ /* software context of a descriptor ring */
struct xgene_enet_desc_ring { struct xgene_enet_desc_ring {
struct net_device *ndev; struct net_device *ndev;
...@@ -124,6 +140,7 @@ struct xgene_enet_pdata { ...@@ -124,6 +140,7 @@ struct xgene_enet_pdata {
int phy_speed; int phy_speed;
struct clk *clk; struct clk *clk;
struct platform_device *pdev; struct platform_device *pdev;
enum xgene_enet_id enet_id;
struct xgene_enet_desc_ring *tx_ring; struct xgene_enet_desc_ring *tx_ring;
struct xgene_enet_desc_ring *rx_ring; struct xgene_enet_desc_ring *rx_ring;
char *dev_name; char *dev_name;
......
...@@ -122,7 +122,6 @@ static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd, ...@@ -122,7 +122,6 @@ static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd,
return true; return true;
} }
static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata,
u32 rd_addr, u32 *rd_data) u32 rd_addr, u32 *rd_data)
{ {
......
...@@ -24,6 +24,23 @@ ...@@ -24,6 +24,23 @@
#define BLOCK_AXG_MAC_OFFSET 0x0800 #define BLOCK_AXG_MAC_OFFSET 0x0800
#define BLOCK_AXG_MAC_CSR_OFFSET 0x2000 #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_0 0x0000
#define AXGMAC_CONFIG_1 0x0004 #define AXGMAC_CONFIG_1 0x0004
#define HSTMACRST BIT(31) #define HSTMACRST BIT(31)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment