#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;
        }
 }
 
+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)
        }
        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",
        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;
        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);
        }
 
        /* 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) {
        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) {
                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;
                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)
        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));
                          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;
 
 #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},
        {},
 };