]> git.sur5r.net Git - u-boot/blobdiff - drivers/net/mvpp2.c
net: mvpp2: Restructure probe / init functions
[u-boot] / drivers / net / mvpp2.c
index e5b42b9e66fb2ee787f14ad622a8a8d188cdf121..1c83884d19d4d6a386985d22a78ba000d4a78d95 100644 (file)
@@ -6,7 +6,7 @@
  * Marcin Wojtas <mw@semihalf.com>
  *
  * U-Boot version:
- * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2016-2017 Stefan Roese <sr@denx.de>
  *
  * This file is licensed under the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
@@ -143,6 +143,7 @@ do {                                                                        \
 /* Descriptor Manager Top Registers */
 #define MVPP2_RXQ_NUM_REG                      0x2040
 #define MVPP2_RXQ_DESC_ADDR_REG                        0x2044
+#define     MVPP22_DESC_ADDR_OFFS              8
 #define MVPP2_RXQ_DESC_SIZE_REG                        0x2048
 #define     MVPP2_RXQ_DESC_SIZE_MASK           0x3ff0
 #define MVPP2_RXQ_STATUS_UPDATE_REG(rxq)       (0x3000 + 4 * (rxq))
@@ -184,6 +185,7 @@ do {                                                                        \
 #define MVPP2_TXQ_RSVD_CLR_REG                 0x20b8
 #define     MVPP2_TXQ_RSVD_CLR_OFFSET          16
 #define MVPP2_AGGR_TXQ_DESC_ADDR_REG(cpu)      (0x2100 + 4 * (cpu))
+#define     MVPP22_AGGR_TXQ_DESC_ADDR_OFFS     8
 #define MVPP2_AGGR_TXQ_DESC_SIZE_REG(cpu)      (0x2140 + 4 * (cpu))
 #define     MVPP2_AGGR_TXQ_DESC_SIZE_MASK      0x3ff0
 #define MVPP2_AGGR_TXQ_STATUS_REG(cpu)         (0x2180 + 4 * (cpu))
@@ -196,9 +198,51 @@ do {                                                                       \
 #define MVPP2_WIN_REMAP(w)                     (0x4040 + ((w) << 2))
 #define MVPP2_BASE_ADDR_ENABLE                 0x4060
 
+/* AXI Bridge Registers */
+#define MVPP22_AXI_BM_WR_ATTR_REG              0x4100
+#define MVPP22_AXI_BM_RD_ATTR_REG              0x4104
+#define MVPP22_AXI_AGGRQ_DESCR_RD_ATTR_REG     0x4110
+#define MVPP22_AXI_TXQ_DESCR_WR_ATTR_REG       0x4114
+#define MVPP22_AXI_TXQ_DESCR_RD_ATTR_REG       0x4118
+#define MVPP22_AXI_RXQ_DESCR_WR_ATTR_REG       0x411c
+#define MVPP22_AXI_RX_DATA_WR_ATTR_REG         0x4120
+#define MVPP22_AXI_TX_DATA_RD_ATTR_REG         0x4130
+#define MVPP22_AXI_RD_NORMAL_CODE_REG          0x4150
+#define MVPP22_AXI_RD_SNOOP_CODE_REG           0x4154
+#define MVPP22_AXI_WR_NORMAL_CODE_REG          0x4160
+#define MVPP22_AXI_WR_SNOOP_CODE_REG           0x4164
+
+/* Values for AXI Bridge registers */
+#define MVPP22_AXI_ATTR_CACHE_OFFS             0
+#define MVPP22_AXI_ATTR_DOMAIN_OFFS            12
+
+#define MVPP22_AXI_CODE_CACHE_OFFS             0
+#define MVPP22_AXI_CODE_DOMAIN_OFFS            4
+
+#define MVPP22_AXI_CODE_CACHE_NON_CACHE                0x3
+#define MVPP22_AXI_CODE_CACHE_WR_CACHE         0x7
+#define MVPP22_AXI_CODE_CACHE_RD_CACHE         0xb
+
+#define MVPP22_AXI_CODE_DOMAIN_OUTER_DOM       2
+#define MVPP22_AXI_CODE_DOMAIN_SYSTEM          3
+
 /* Interrupt Cause and Mask registers */
 #define MVPP2_ISR_RX_THRESHOLD_REG(rxq)                (0x5200 + 4 * (rxq))
-#define MVPP2_ISR_RXQ_GROUP_REG(rxq)           (0x5400 + 4 * (rxq))
+#define MVPP21_ISR_RXQ_GROUP_REG(rxq)          (0x5400 + 4 * (rxq))
+
+#define MVPP22_ISR_RXQ_GROUP_INDEX_REG          0x5400
+#define MVPP22_ISR_RXQ_GROUP_INDEX_SUBGROUP_MASK 0xf
+#define MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_MASK   0x380
+#define MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_OFFSET 7
+
+#define MVPP22_ISR_RXQ_GROUP_INDEX_SUBGROUP_MASK 0xf
+#define MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_MASK   0x380
+
+#define MVPP22_ISR_RXQ_SUB_GROUP_CONFIG_REG     0x5404
+#define MVPP22_ISR_RXQ_SUB_GROUP_STARTQ_MASK    0x1f
+#define MVPP22_ISR_RXQ_SUB_GROUP_SIZE_MASK      0xf00
+#define MVPP22_ISR_RXQ_SUB_GROUP_SIZE_OFFSET    8
+
 #define MVPP2_ISR_ENABLE_REG(port)             (0x5420 + 4 * (port))
 #define     MVPP2_ISR_ENABLE_INTERRUPT(mask)   ((mask) & 0xffff)
 #define     MVPP2_ISR_DISABLE_INTERRUPT(mask)  (((mask) << 16) & 0xffff0000)
@@ -340,6 +384,12 @@ do {                                                                       \
 #define      MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(v) (((v) << 6) & \
                                        MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK)
 
+#define MVPP22_SMI_MISC_CFG_REG                        0x1204
+#define      MVPP22_SMI_POLLING_EN             BIT(10)
+
+#define MVPP22_PORT_BASE                       0x30e00
+#define MVPP22_PORT_OFFSET                     0x1000
+
 #define MVPP2_CAUSE_TXQ_SENT_DESC_ALL_MASK     0xff
 
 /* Descriptor ring Macros */
@@ -347,7 +397,9 @@ do {                                                                        \
        (((index) < (q)->last_desc) ? ((index) + 1) : 0)
 
 /* SMI: 0xc0054 -> offset 0x54 to lms_base */
-#define MVPP2_SMI                              0x0054
+#define MVPP21_SMI                             0x0054
+/* PP2.2: SMI: 0x12a200 -> offset 0x1200 to iface_base */
+#define MVPP22_SMI                             0x1200
 #define     MVPP2_PHY_REG_MASK                 0x1f
 /* SMI register fields */
 #define     MVPP2_SMI_DATA_OFFS                        0       /* Data */
@@ -404,9 +456,6 @@ do {                                                                        \
 /* Maximum number of TXQs used by single port */
 #define MVPP2_MAX_TXQ                  8
 
-/* Maximum number of RXQs used by single port */
-#define MVPP2_MAX_RXQ                  8
-
 /* Default number of TXQs in use */
 #define MVPP2_DEFAULT_TXQ              1
 
@@ -414,9 +463,6 @@ do {                                                                        \
 #define MVPP2_DEFAULT_RXQ              1
 #define CONFIG_MV_ETH_RXQ              8       /* increment by 8 */
 
-/* Total number of RXQs available to all ports */
-#define MVPP2_RXQ_TOTAL_NUM            (MVPP2_MAX_PORTS * MVPP2_MAX_RXQ)
-
 /* Max number of Rx descriptors */
 #define MVPP2_MAX_RXD                  16
 
@@ -436,9 +482,23 @@ do {                                                                       \
 #define MVPP2_TX_DESC_ALIGN            (MVPP2_DESC_ALIGNED_SIZE - 1)
 
 /* RX FIFO constants */
-#define MVPP2_RX_FIFO_PORT_DATA_SIZE   0x2000
-#define MVPP2_RX_FIFO_PORT_ATTR_SIZE   0x80
-#define MVPP2_RX_FIFO_PORT_MIN_PKT     0x80
+#define MVPP21_RX_FIFO_PORT_DATA_SIZE          0x2000
+#define MVPP21_RX_FIFO_PORT_ATTR_SIZE          0x80
+#define MVPP22_RX_FIFO_10GB_PORT_DATA_SIZE     0x8000
+#define MVPP22_RX_FIFO_2_5GB_PORT_DATA_SIZE    0x2000
+#define MVPP22_RX_FIFO_1GB_PORT_DATA_SIZE      0x1000
+#define MVPP22_RX_FIFO_10GB_PORT_ATTR_SIZE     0x200
+#define MVPP22_RX_FIFO_2_5GB_PORT_ATTR_SIZE    0x80
+#define MVPP22_RX_FIFO_1GB_PORT_ATTR_SIZE      0x40
+#define MVPP2_RX_FIFO_PORT_MIN_PKT             0x80
+
+/* TX general registers */
+#define MVPP22_TX_FIFO_SIZE_REG(eth_tx_port)   (0x8860 + ((eth_tx_port) << 2))
+#define MVPP22_TX_FIFO_SIZE_MASK               0xf
+
+/* TX FIFO constants */
+#define MVPP2_TX_FIFO_DATA_SIZE_10KB           0xa
+#define MVPP2_TX_FIFO_DATA_SIZE_3KB            0x3
 
 /* RX buffer constants */
 #define MVPP2_SKB_SHINFO_SIZE \
@@ -700,6 +760,8 @@ struct mvpp2 {
        /* Shared registers' base addresses */
        void __iomem *base;
        void __iomem *lms_base;
+       void __iomem *iface_base;
+       void __iomem *mdio_base;
 
        /* List of pointers to port structures */
        struct mvpp2_port **port_list;
@@ -721,7 +783,12 @@ struct mvpp2 {
        /* HW version */
        enum { MVPP21, MVPP22 } hw_version;
 
+       /* Maximum number of RXQs per port */
+       unsigned int max_port_rxqs;
+
        struct mii_dev *bus;
+
+       int probe_done;
 };
 
 struct mvpp2_pcpu_stats {
@@ -734,6 +801,11 @@ struct mvpp2_pcpu_stats {
 struct mvpp2_port {
        u8 id;
 
+       /* Index of the port from the "group of ports" complex point
+        * of view
+        */
+       int gop_id;
+
        int irq;
 
        struct mvpp2 *priv;
@@ -1032,6 +1104,8 @@ static int rxq_number = MVPP2_DEFAULT_RXQ;
 /* Number of TXQs used by single port */
 static int txq_number = MVPP2_DEFAULT_TXQ;
 
+static int base_id;
+
 #define MVPP2_DRIVER_NAME "mvpp2"
 #define MVPP2_DRIVER_VERSION "1.0"
 
@@ -2755,16 +2829,18 @@ static void mvpp2_defaults_set(struct mvpp2_port *port)
 {
        int tx_port_num, val, queue, ptxq, lrxq;
 
-       /* Configure port to loopback if needed */
-       if (port->flags & MVPP2_F_LOOPBACK)
-               mvpp2_port_loopback_set(port);
-
-       /* Update TX FIFO MIN Threshold */
-       val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
-       val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
-       /* Min. TX threshold must be less than minimal packet length */
-       val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(64 - 4 - 2);
-       writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+       if (port->priv->hw_version == MVPP21) {
+               /* Configure port to loopback if needed */
+               if (port->flags & MVPP2_F_LOOPBACK)
+                       mvpp2_port_loopback_set(port);
+
+               /* Update TX FIFO MIN Threshold */
+               val = readl(port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+               val &= ~MVPP2_GMAC_TX_FIFO_MIN_TH_ALL_MASK;
+               /* Min. TX threshold must be less than minimal packet length */
+               val |= MVPP2_GMAC_TX_FIFO_MIN_TH_MASK(64 - 4 - 2);
+               writel(val, port->base + MVPP2_GMAC_PORT_FIFO_CFG_1_REG);
+       }
 
        /* Disable Legacy WRR, Disable EJP, Release from reset */
        tx_port_num = mvpp2_egress_port(port);
@@ -3105,6 +3181,8 @@ static int mvpp2_aggr_txq_init(struct udevice *dev,
                               int desc_num, int cpu,
                               struct mvpp2 *priv)
 {
+       u32 txq_dma;
+
        /* Allocate memory for TX descriptors */
        aggr_txq->descs = buffer_loc.aggr_tx_descs;
        aggr_txq->descs_dma = (dma_addr_t)buffer_loc.aggr_tx_descs;
@@ -3121,10 +3199,16 @@ static int mvpp2_aggr_txq_init(struct udevice *dev,
        aggr_txq->next_desc_to_proc = mvpp2_read(priv,
                                                 MVPP2_AGGR_TXQ_INDEX_REG(cpu));
 
-       /* Set Tx descriptors queue starting address */
-       /* indirect access */
-       mvpp2_write(priv, MVPP2_AGGR_TXQ_DESC_ADDR_REG(cpu),
-                   aggr_txq->descs_dma);
+       /* Set Tx descriptors queue starting address indirect
+        * access
+        */
+       if (priv->hw_version == MVPP21)
+               txq_dma = aggr_txq->descs_dma;
+       else
+               txq_dma = aggr_txq->descs_dma >>
+                       MVPP22_AGGR_TXQ_DESC_ADDR_OFFS;
+
+       mvpp2_write(priv, MVPP2_AGGR_TXQ_DESC_ADDR_REG(cpu), txq_dma);
        mvpp2_write(priv, MVPP2_AGGR_TXQ_DESC_SIZE_REG(cpu), desc_num);
 
        return 0;
@@ -3135,6 +3219,8 @@ static int mvpp2_rxq_init(struct mvpp2_port *port,
                          struct mvpp2_rx_queue *rxq)
 
 {
+       u32 rxq_dma;
+
        rxq->size = port->rx_ring_size;
 
        /* Allocate memory for RX descriptors */
@@ -3153,7 +3239,11 @@ static int mvpp2_rxq_init(struct mvpp2_port *port,
 
        /* Set Rx descriptors queue starting address - indirect access */
        mvpp2_write(port->priv, MVPP2_RXQ_NUM_REG, rxq->id);
-       mvpp2_write(port->priv, MVPP2_RXQ_DESC_ADDR_REG, rxq->descs_dma);
+       if (port->priv->hw_version == MVPP21)
+               rxq_dma = rxq->descs_dma;
+       else
+               rxq_dma = rxq->descs_dma >> MVPP22_DESC_ADDR_OFFS;
+       mvpp2_write(port->priv, MVPP2_RXQ_DESC_ADDR_REG, rxq_dma);
        mvpp2_write(port->priv, MVPP2_RXQ_DESC_SIZE_REG, rxq->size);
        mvpp2_write(port->priv, MVPP2_RXQ_INDEX_REG, 0);
 
@@ -3252,7 +3342,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
 
        mvpp2_write(port->priv, MVPP2_TXQ_PREF_BUF_REG,
                    MVPP2_PREF_BUF_PTR(desc) | MVPP2_PREF_BUF_SIZE_16 |
-                   MVPP2_PREF_BUF_THRESH(desc_per_txq/2));
+                   MVPP2_PREF_BUF_THRESH(desc_per_txq / 2));
 
        /* WRR / EJP configuration - indirect access */
        tx_port_num = mvpp2_egress_port(port);
@@ -3612,9 +3702,12 @@ static int mvpp2_open(struct udevice *dev, struct mvpp2_port *port)
 
 static void mvpp2_port_power_up(struct mvpp2_port *port)
 {
+       struct mvpp2 *priv = port->priv;
+
        mvpp2_port_mii_set(port);
        mvpp2_port_periodic_xon_disable(port);
-       mvpp2_port_fc_adv_enable(port);
+       if (priv->hw_version == MVPP21)
+               mvpp2_port_fc_adv_enable(port);
        mvpp2_port_reset(port);
 }
 
@@ -3625,7 +3718,8 @@ static int mvpp2_port_init(struct udevice *dev, struct mvpp2_port *port)
        struct mvpp2_txq_pcpu *txq_pcpu;
        int queue, cpu, err;
 
-       if (port->first_rxq + rxq_number > MVPP2_RXQ_TOTAL_NUM)
+       if (port->first_rxq + rxq_number >
+           MVPP2_MAX_PORTS * priv->max_port_rxqs)
                return -EINVAL;
 
        /* Disable port */
@@ -3686,7 +3780,19 @@ static int mvpp2_port_init(struct udevice *dev, struct mvpp2_port *port)
        }
 
        /* Configure Rx queue group interrupt for this port */
-       mvpp2_write(priv, MVPP2_ISR_RXQ_GROUP_REG(port->id), CONFIG_MV_ETH_RXQ);
+       if (priv->hw_version == MVPP21) {
+               mvpp2_write(priv, MVPP21_ISR_RXQ_GROUP_REG(port->id),
+                           CONFIG_MV_ETH_RXQ);
+       } else {
+               u32 val;
+
+               val = (port->id << MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_OFFSET);
+               mvpp2_write(priv, MVPP22_ISR_RXQ_GROUP_INDEX_REG, val);
+
+               val = (CONFIG_MV_ETH_RXQ <<
+                      MVPP22_ISR_RXQ_SUB_GROUP_SIZE_OFFSET);
+               mvpp2_write(priv, MVPP22_ISR_RXQ_SUB_GROUP_CONFIG_REG, val);
+       }
 
        /* Create Rx descriptor rings */
        for (queue = 0; queue < rxq_number; queue++) {
@@ -3717,20 +3823,14 @@ static int mvpp2_port_init(struct udevice *dev, struct mvpp2_port *port)
        return 0;
 }
 
-/* Ports initialization */
-static int mvpp2_port_probe(struct udevice *dev,
-                           struct mvpp2_port *port,
-                           int port_node,
-                           struct mvpp2 *priv,
-                           int *next_first_rxq)
+static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port)
 {
+       int port_node = dev_of_offset(dev);
+       const char *phy_mode_str;
        int phy_node;
        u32 id;
        u32 phyaddr;
-       const char *phy_mode_str;
        int phy_mode = -1;
-       int priv_common_regs_num = 2;
-       int err;
 
        phy_node = fdtdec_lookup_phandle(gd->fdt_blob, port_node, "phy");
        if (phy_node < 0) {
@@ -3754,32 +3854,37 @@ static int mvpp2_port_probe(struct udevice *dev,
 
        phyaddr = fdtdec_get_int(gd->fdt_blob, phy_node, "reg", 0);
 
-       port->priv = priv;
        port->id = id;
-       port->first_rxq = *next_first_rxq;
+       if (port->priv->hw_version == MVPP21)
+               port->first_rxq = port->id * rxq_number;
+       else
+               port->first_rxq = port->id * port->priv->max_port_rxqs;
        port->phy_node = phy_node;
        port->phy_interface = phy_mode;
        port->phyaddr = phyaddr;
 
-       port->base = (void __iomem *)dev_get_addr_index(dev->parent,
-                                                       priv_common_regs_num
-                                                       + id);
-       if (IS_ERR(port->base))
-               return PTR_ERR(port->base);
+       return 0;
+}
+
+/* Ports initialization */
+static int mvpp2_port_probe(struct udevice *dev,
+                           struct mvpp2_port *port,
+                           int port_node,
+                           struct mvpp2 *priv)
+{
+       int err;
 
        port->tx_ring_size = MVPP2_MAX_TXD;
        port->rx_ring_size = MVPP2_MAX_RXD;
 
        err = mvpp2_port_init(dev, port);
        if (err < 0) {
-               dev_err(&pdev->dev, "failed to init port %d\n", id);
+               dev_err(&pdev->dev, "failed to init port %d\n", port->id);
                return err;
        }
        mvpp2_port_power_up(port);
 
-       /* Increment the first Rx queue number to be used by the next port */
-       *next_first_rxq += CONFIG_MV_ETH_RXQ;
-       priv->port_list[id] = port;
+       priv->port_list[port->id] = port;
        return 0;
 }
 
@@ -3822,10 +3927,35 @@ static void mvpp2_rx_fifo_init(struct mvpp2 *priv)
        int port;
 
        for (port = 0; port < MVPP2_MAX_PORTS; port++) {
-               mvpp2_write(priv, MVPP2_RX_DATA_FIFO_SIZE_REG(port),
-                           MVPP2_RX_FIFO_PORT_DATA_SIZE);
-               mvpp2_write(priv, MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
-                           MVPP2_RX_FIFO_PORT_ATTR_SIZE);
+               if (priv->hw_version == MVPP22) {
+                       if (port == 0) {
+                               mvpp2_write(priv,
+                                           MVPP2_RX_DATA_FIFO_SIZE_REG(port),
+                                           MVPP22_RX_FIFO_10GB_PORT_DATA_SIZE);
+                               mvpp2_write(priv,
+                                           MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
+                                           MVPP22_RX_FIFO_10GB_PORT_ATTR_SIZE);
+                       } else if (port == 1) {
+                               mvpp2_write(priv,
+                                           MVPP2_RX_DATA_FIFO_SIZE_REG(port),
+                                           MVPP22_RX_FIFO_2_5GB_PORT_DATA_SIZE);
+                               mvpp2_write(priv,
+                                           MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
+                                           MVPP22_RX_FIFO_2_5GB_PORT_ATTR_SIZE);
+                       } else {
+                               mvpp2_write(priv,
+                                           MVPP2_RX_DATA_FIFO_SIZE_REG(port),
+                                           MVPP22_RX_FIFO_1GB_PORT_DATA_SIZE);
+                               mvpp2_write(priv,
+                                           MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
+                                           MVPP22_RX_FIFO_1GB_PORT_ATTR_SIZE);
+                       }
+               } else {
+                       mvpp2_write(priv, MVPP2_RX_DATA_FIFO_SIZE_REG(port),
+                                   MVPP21_RX_FIFO_PORT_DATA_SIZE);
+                       mvpp2_write(priv, MVPP2_RX_ATTR_FIFO_SIZE_REG(port),
+                                   MVPP21_RX_FIFO_PORT_ATTR_SIZE);
+               }
        }
 
        mvpp2_write(priv, MVPP2_RX_MIN_PKT_SIZE_REG,
@@ -3833,6 +3963,78 @@ static void mvpp2_rx_fifo_init(struct mvpp2 *priv)
        mvpp2_write(priv, MVPP2_RX_FIFO_INIT_REG, 0x1);
 }
 
+/* Initialize Tx FIFO's */
+static void mvpp2_tx_fifo_init(struct mvpp2 *priv)
+{
+       int port, val;
+
+       for (port = 0; port < MVPP2_MAX_PORTS; port++) {
+               /* Port 0 supports 10KB TX FIFO */
+               if (port == 0) {
+                       val = MVPP2_TX_FIFO_DATA_SIZE_10KB &
+                               MVPP22_TX_FIFO_SIZE_MASK;
+               } else {
+                       val = MVPP2_TX_FIFO_DATA_SIZE_3KB &
+                               MVPP22_TX_FIFO_SIZE_MASK;
+               }
+               mvpp2_write(priv, MVPP22_TX_FIFO_SIZE_REG(port), val);
+       }
+}
+
+static void mvpp2_axi_init(struct mvpp2 *priv)
+{
+       u32 val, rdval, wrval;
+
+       mvpp2_write(priv, MVPP22_BM_ADDR_HIGH_RLS_REG, 0x0);
+
+       /* AXI Bridge Configuration */
+
+       rdval = MVPP22_AXI_CODE_CACHE_RD_CACHE
+               << MVPP22_AXI_ATTR_CACHE_OFFS;
+       rdval |= MVPP22_AXI_CODE_DOMAIN_OUTER_DOM
+               << MVPP22_AXI_ATTR_DOMAIN_OFFS;
+
+       wrval = MVPP22_AXI_CODE_CACHE_WR_CACHE
+               << MVPP22_AXI_ATTR_CACHE_OFFS;
+       wrval |= MVPP22_AXI_CODE_DOMAIN_OUTER_DOM
+               << MVPP22_AXI_ATTR_DOMAIN_OFFS;
+
+       /* BM */
+       mvpp2_write(priv, MVPP22_AXI_BM_WR_ATTR_REG, wrval);
+       mvpp2_write(priv, MVPP22_AXI_BM_RD_ATTR_REG, rdval);
+
+       /* Descriptors */
+       mvpp2_write(priv, MVPP22_AXI_AGGRQ_DESCR_RD_ATTR_REG, rdval);
+       mvpp2_write(priv, MVPP22_AXI_TXQ_DESCR_WR_ATTR_REG, wrval);
+       mvpp2_write(priv, MVPP22_AXI_TXQ_DESCR_RD_ATTR_REG, rdval);
+       mvpp2_write(priv, MVPP22_AXI_RXQ_DESCR_WR_ATTR_REG, wrval);
+
+       /* Buffer Data */
+       mvpp2_write(priv, MVPP22_AXI_TX_DATA_RD_ATTR_REG, rdval);
+       mvpp2_write(priv, MVPP22_AXI_RX_DATA_WR_ATTR_REG, wrval);
+
+       val = MVPP22_AXI_CODE_CACHE_NON_CACHE
+               << MVPP22_AXI_CODE_CACHE_OFFS;
+       val |= MVPP22_AXI_CODE_DOMAIN_SYSTEM
+               << MVPP22_AXI_CODE_DOMAIN_OFFS;
+       mvpp2_write(priv, MVPP22_AXI_RD_NORMAL_CODE_REG, val);
+       mvpp2_write(priv, MVPP22_AXI_WR_NORMAL_CODE_REG, val);
+
+       val = MVPP22_AXI_CODE_CACHE_RD_CACHE
+               << MVPP22_AXI_CODE_CACHE_OFFS;
+       val |= MVPP22_AXI_CODE_DOMAIN_OUTER_DOM
+               << MVPP22_AXI_CODE_DOMAIN_OFFS;
+
+       mvpp2_write(priv, MVPP22_AXI_RD_SNOOP_CODE_REG, val);
+
+       val = MVPP22_AXI_CODE_CACHE_WR_CACHE
+               << MVPP22_AXI_CODE_CACHE_OFFS;
+       val |= MVPP22_AXI_CODE_DOMAIN_OUTER_DOM
+               << MVPP22_AXI_CODE_DOMAIN_OFFS;
+
+       mvpp2_write(priv, MVPP22_AXI_WR_SNOOP_CODE_REG, val);
+}
+
 /* Initialize network controller common part HW */
 static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv)
 {
@@ -3841,7 +4043,8 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv)
        u32 val;
 
        /* Checks for hardware constraints (U-Boot uses only one rxq) */
-       if ((rxq_number > MVPP2_MAX_RXQ) || (txq_number > MVPP2_MAX_TXQ)) {
+       if ((rxq_number > priv->max_port_rxqs) ||
+           (txq_number > MVPP2_MAX_TXQ)) {
                dev_err(&pdev->dev, "invalid queue size parameter\n");
                return -EINVAL;
        }
@@ -3851,10 +4054,19 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv)
        if (dram_target_info)
                mvpp2_conf_mbus_windows(dram_target_info, priv);
 
+       if (priv->hw_version == MVPP22)
+               mvpp2_axi_init(priv);
+
        /* Disable HW PHY polling */
-       val = readl(priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
-       val |= MVPP2_PHY_AN_STOP_SMI0_MASK;
-       writel(val, priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
+       if (priv->hw_version == MVPP21) {
+               val = readl(priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
+               val |= MVPP2_PHY_AN_STOP_SMI0_MASK;
+               writel(val, priv->lms_base + MVPP2_PHY_AN_CFG0_REG);
+       } else {
+               val = readl(priv->iface_base + MVPP22_SMI_MISC_CFG_REG);
+               val &= ~MVPP22_SMI_POLLING_EN;
+               writel(val, priv->iface_base + MVPP22_SMI_MISC_CFG_REG);
+       }
 
        /* Allocate and initialize aggregated TXQs */
        priv->aggr_txqs = devm_kcalloc(dev, num_present_cpus(),
@@ -3875,13 +4087,32 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv)
        /* Rx Fifo Init */
        mvpp2_rx_fifo_init(priv);
 
+       /* Tx Fifo Init */
+       if (priv->hw_version == MVPP22)
+               mvpp2_tx_fifo_init(priv);
+
        /* Reset Rx queue group interrupt configuration */
-       for (i = 0; i < MVPP2_MAX_PORTS; i++)
-               mvpp2_write(priv, MVPP2_ISR_RXQ_GROUP_REG(i),
-                           CONFIG_MV_ETH_RXQ);
+       for (i = 0; i < MVPP2_MAX_PORTS; i++) {
+               if (priv->hw_version == MVPP21) {
+                       mvpp2_write(priv, MVPP21_ISR_RXQ_GROUP_REG(i),
+                                   CONFIG_MV_ETH_RXQ);
+                       continue;
+               } else {
+                       u32 val;
 
-       writel(MVPP2_EXT_GLOBAL_CTRL_DEFAULT,
-              priv->lms_base + MVPP2_MNG_EXTENDED_GLOBAL_CTRL_REG);
+                       val = (i << MVPP22_ISR_RXQ_GROUP_INDEX_GROUP_OFFSET);
+                       mvpp2_write(priv, MVPP22_ISR_RXQ_GROUP_INDEX_REG, val);
+
+                       val = (CONFIG_MV_ETH_RXQ <<
+                              MVPP22_ISR_RXQ_SUB_GROUP_SIZE_OFFSET);
+                       mvpp2_write(priv,
+                                   MVPP22_ISR_RXQ_SUB_GROUP_CONFIG_REG, val);
+               }
+       }
+
+       if (priv->hw_version == MVPP21)
+               writel(MVPP2_EXT_GLOBAL_CTRL_DEFAULT,
+                      priv->lms_base + MVPP2_MNG_EXTENDED_GLOBAL_CTRL_REG);
 
        /* Allow cache snoop when transmiting packets */
        mvpp2_write(priv, MVPP2_TX_SNOOP_REG, 0x1);
@@ -3912,7 +4143,7 @@ static int smi_wait_ready(struct mvpp2 *priv)
        /* wait till the SMI is not busy */
        do {
                /* read smi register */
-               smi_reg = readl(priv->lms_base + MVPP2_SMI);
+               smi_reg = readl(priv->mdio_base);
                if (timeout-- == 0) {
                        printf("Error: SMI busy timeout\n");
                        return -EFAULT;
@@ -3954,14 +4185,14 @@ static int mpp2_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
                | MVPP2_SMI_OPCODE_READ;
 
        /* write the smi register */
-       writel(smi_reg, priv->lms_base + MVPP2_SMI);
+       writel(smi_reg, priv->mdio_base);
 
        /* wait till read value is ready */
        timeout = MVPP2_SMI_TIMEOUT;
 
        do {
                /* read smi register */
-               smi_reg = readl(priv->lms_base + MVPP2_SMI);
+               smi_reg = readl(priv->mdio_base);
                if (timeout-- == 0) {
                        printf("Err: SMI read ready timeout\n");
                        return -EFAULT;
@@ -3972,7 +4203,7 @@ static int mpp2_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
        for (timeout = 0; timeout < MVPP2_SMI_TIMEOUT; timeout++)
                ;
 
-       return readl(priv->lms_base + MVPP2_SMI) & MVPP2_SMI_DATA_MASK;
+       return readl(priv->mdio_base) & MVPP2_SMI_DATA_MASK;
 }
 
 /*
@@ -4009,7 +4240,7 @@ static int mpp2_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
        smi_reg &= ~MVPP2_SMI_OPCODE_READ;
 
        /* write the smi register */
-       writel(smi_reg, priv->lms_base + MVPP2_SMI);
+       writel(smi_reg, priv->mdio_base);
 
        return 0;
 }
@@ -4197,43 +4428,6 @@ static void mvpp2_stop(struct udevice *dev)
        mvpp2_cleanup_txqs(port);
 }
 
-static int mvpp2_probe(struct udevice *dev)
-{
-       struct mvpp2_port *port = dev_get_priv(dev);
-       struct mvpp2 *priv = dev_get_priv(dev->parent);
-       int err;
-
-       /* Initialize network controller */
-       err = mvpp2_init(dev, priv);
-       if (err < 0) {
-               dev_err(&pdev->dev, "failed to initialize controller\n");
-               return err;
-       }
-
-       return mvpp2_port_probe(dev, port, dev_of_offset(dev), priv,
-                               &buffer_loc.first_rxq);
-}
-
-static const struct eth_ops mvpp2_ops = {
-       .start          = mvpp2_start,
-       .send           = mvpp2_send,
-       .recv           = mvpp2_recv,
-       .stop           = mvpp2_stop,
-};
-
-static struct driver mvpp2_driver = {
-       .name   = "mvpp2",
-       .id     = UCLASS_ETH,
-       .probe  = mvpp2_probe,
-       .ops    = &mvpp2_ops,
-       .priv_auto_alloc_size = sizeof(struct mvpp2_port),
-       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
-};
-
-/*
- * Use a MISC device to bind the n instances (child nodes) of the
- * network base controller in UCLASS_ETH.
- */
 static int mvpp2_base_probe(struct udevice *dev)
 {
        struct mvpp2 *priv = dev_get_priv(dev);
@@ -4284,14 +4478,32 @@ static int mvpp2_base_probe(struct udevice *dev)
                size += RX_BUFFER_SIZE;
        }
 
+       /* Clear the complete area so that all descriptors are cleared */
+       memset(bd_space, 0, size);
+
        /* Save base addresses for later use */
        priv->base = (void *)dev_get_addr_index(dev, 0);
        if (IS_ERR(priv->base))
                return PTR_ERR(priv->base);
 
-       priv->lms_base = (void *)dev_get_addr_index(dev, 1);
-       if (IS_ERR(priv->lms_base))
-               return PTR_ERR(priv->lms_base);
+       if (priv->hw_version == MVPP21) {
+               priv->lms_base = (void *)dev_get_addr_index(dev, 1);
+               if (IS_ERR(priv->lms_base))
+                       return PTR_ERR(priv->lms_base);
+
+               priv->mdio_base = priv->lms_base + MVPP21_SMI;
+       } else {
+               priv->iface_base = (void *)dev_get_addr_index(dev, 1);
+               if (IS_ERR(priv->iface_base))
+                       return PTR_ERR(priv->iface_base);
+
+               priv->mdio_base = priv->iface_base + MVPP22_SMI;
+       }
+
+       if (priv->hw_version == MVPP21)
+               priv->max_port_rxqs = 8;
+       else
+               priv->max_port_rxqs = 32;
 
        /* Finally create and register the MDIO bus driver */
        bus = mdio_alloc();
@@ -4309,6 +4521,77 @@ static int mvpp2_base_probe(struct udevice *dev)
        return mdio_register(bus);
 }
 
+static int mvpp2_probe(struct udevice *dev)
+{
+       struct mvpp2_port *port = dev_get_priv(dev);
+       struct mvpp2 *priv = dev_get_priv(dev->parent);
+       int err;
+
+       /* Only call the probe function for the parent once */
+       if (!priv->probe_done) {
+               err = mvpp2_base_probe(dev->parent);
+               priv->probe_done = 1;
+       }
+
+       port->priv = dev_get_priv(dev->parent);
+
+       err = phy_info_parse(dev, port);
+       if (err)
+               return err;
+
+       /*
+        * We need the port specific io base addresses at this stage, since
+        * gop_port_init() accesses these registers
+        */
+       if (priv->hw_version == MVPP21) {
+               int priv_common_regs_num = 2;
+
+               port->base = (void __iomem *)dev_get_addr_index(
+                       dev->parent, priv_common_regs_num + port->id);
+               if (IS_ERR(port->base))
+                       return PTR_ERR(port->base);
+       } else {
+               port->gop_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
+                                             "gop-port-id", -1);
+               if (port->id == -1) {
+                       dev_err(&pdev->dev, "missing gop-port-id value\n");
+                       return -EINVAL;
+               }
+
+               port->base = priv->iface_base + MVPP22_PORT_BASE +
+                       port->gop_id * MVPP22_PORT_OFFSET;
+       }
+
+       /* Initialize network controller */
+       err = mvpp2_init(dev, priv);
+       if (err < 0) {
+               dev_err(&pdev->dev, "failed to initialize controller\n");
+               return err;
+       }
+
+       return mvpp2_port_probe(dev, port, dev_of_offset(dev), priv);
+}
+
+static const struct eth_ops mvpp2_ops = {
+       .start          = mvpp2_start,
+       .send           = mvpp2_send,
+       .recv           = mvpp2_recv,
+       .stop           = mvpp2_stop,
+};
+
+static struct driver mvpp2_driver = {
+       .name   = "mvpp2",
+       .id     = UCLASS_ETH,
+       .probe  = mvpp2_probe,
+       .ops    = &mvpp2_ops,
+       .priv_auto_alloc_size = sizeof(struct mvpp2_port),
+       .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+
+/*
+ * Use a MISC device to bind the n instances (child nodes) of the
+ * network base controller in UCLASS_ETH.
+ */
 static int mvpp2_base_bind(struct udevice *parent)
 {
        const void *blob = gd->fdt_blob;
@@ -4319,6 +4602,7 @@ static int mvpp2_base_bind(struct udevice *parent)
        char *name;
        int subnode;
        u32 id;
+       int base_id_add;
 
        /* Lookup eth driver */
        drv = lists_uclass_lookup(UCLASS_ETH);
@@ -4327,7 +4611,12 @@ static int mvpp2_base_bind(struct udevice *parent)
                return -ENOENT;
        }
 
+       base_id_add = base_id;
+
        fdt_for_each_subnode(subnode, blob, node) {
+               /* Increment base_id for all subnodes, also the disabled ones */
+               base_id++;
+
                /* Skip disabled ports */
                if (!fdtdec_get_is_enabled(blob, subnode))
                        continue;
@@ -4337,6 +4626,7 @@ static int mvpp2_base_bind(struct udevice *parent)
                        return -ENOMEM;
 
                id = fdtdec_get_int(blob, subnode, "port-id", -1);
+               id += base_id_add;
 
                name = calloc(1, 16);
                sprintf(name, "mvpp2-%d", id);
@@ -4354,6 +4644,10 @@ static const struct udevice_id mvpp2_ids[] = {
                .compatible = "marvell,armada-375-pp2",
                .data = MVPP21,
        },
+       {
+               .compatible = "marvell,armada-7k-pp22",
+               .data = MVPP22,
+       },
        { }
 };
 
@@ -4362,6 +4656,5 @@ U_BOOT_DRIVER(mvpp2_base) = {
        .id     = UCLASS_MISC,
        .of_match = mvpp2_ids,
        .bind   = mvpp2_base_bind,
-       .probe  = mvpp2_base_probe,
        .priv_auto_alloc_size = sizeof(struct mvpp2),
 };