drivers: net: xgene: Add 10GbE support with ring manager v2
authorIyappan Subramanian <isubramanian@apm.com>
Tue, 28 Apr 2015 20:52:39 +0000 (13:52 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 30 Apr 2015 20:03:13 +0000 (16:03 -0400)
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
drivers/net/ethernet/apm/xgene/xgene_enet_main.c
drivers/net/ethernet/apm/xgene/xgene_enet_main.h
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h

index 1dbc10a63458ff888e5b55fde3c79dcdb6b098fd..5176fcb9f413436cce31fbc379c7948c8a92fc62 100644 (file)
@@ -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
index b3bbc6872bd53108a9df55379fff4d1aa78a8d6e..513bfa4fb79009262396290876816a11a481238c 100644 (file)
@@ -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;
        }
 
-       base_addr = pdata->base_addr - (pdata->port_id * MAC_OFFSET);
+       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,24 +1089,44 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata)
                break;
        }
 
-       switch (pdata->port_id) {
-       case 0:
-               pdata->cpu_bufnum = START_CPU_BUFNUM_0;
-               pdata->eth_bufnum = START_ETH_BUFNUM_0;
-               pdata->bp_bufnum = START_BP_BUFNUM_0;
-               pdata->ring_num = START_RING_NUM_0;
-               break;
-       case 1:
-               pdata->cpu_bufnum = START_CPU_BUFNUM_1;
-               pdata->eth_bufnum = START_ETH_BUFNUM_1;
-               pdata->bp_bufnum = START_BP_BUFNUM_1;
-               pdata->ring_num = START_RING_NUM_1;
-               break;
-       default:
-               break;
+       if (pdata->enet_id == XGENE_ENET1) {
+               switch (pdata->port_id) {
+               case 0:
+                       pdata->cpu_bufnum = START_CPU_BUFNUM_0;
+                       pdata->eth_bufnum = START_ETH_BUFNUM_0;
+                       pdata->bp_bufnum = START_BP_BUFNUM_0;
+                       pdata->ring_num = START_RING_NUM_0;
+                       break;
+               case 1:
+                       pdata->cpu_bufnum = START_CPU_BUFNUM_1;
+                       pdata->eth_bufnum = START_ETH_BUFNUM_1;
+                       pdata->bp_bufnum = START_BP_BUFNUM_1;
+                       pdata->ring_num = START_RING_NUM_1;
+                       break;
+               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;
        }
-
-       pdata->ring_ops = &xgene_ring1_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},
        {},
 };
 
index a44f4a3e938824090fdb8612c980d0564d17ee3b..ef1887be9428564e61bb414b618ec4a6a64b3083 100644 (file)
@@ -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
 #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;
index a18a9d1f11432d4469d2d711ec633f22565017eb..27ba2fe3fca61888d6267eddfc3c9844e2140454 100644 (file)
@@ -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)
 {
index 5a5296a6d1df0a65e806dc7c9b3f78f5f6b27608..d07ee5ea3046588d1d7216bc7e5f2d6f38b0e29b 100644 (file)
 #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)