common: Drop linux/bitops.h from common header
[platform/kernel/u-boot.git] / drivers / net / mvpp2.c
index 8ffe6c8..19b9375 100644 (file)
  */
 
 #include <common.h>
+#include <cpu_func.h>
 #include <dm.h>
+#include <asm/cache.h>
 #include <dm/device-internal.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
 #include <dm/lists.h>
 #include <net.h>
 #include <netdev.h>
 #include <config.h>
 #include <malloc.h>
 #include <asm/io.h>
+#include <linux/bitops.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <phy.h>
 #include <miiphy.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
 #include <linux/compat.h>
+#include <linux/libfdt.h>
 #include <linux/mbus.h>
+#include <asm-generic/gpio.h>
+#include <fdt_support.h>
+#include <linux/mdio.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-/* Some linux -> U-Boot compatibility stuff */
-#define netdev_err(dev, fmt, args...)          \
-       printf(fmt, ##args)
-#define netdev_warn(dev, fmt, args...)         \
-       printf(fmt, ##args)
-#define netdev_info(dev, fmt, args...)         \
-       printf(fmt, ##args)
-#define netdev_dbg(dev, fmt, args...)          \
-       printf(fmt, ##args)
-
-#define ETH_ALEN       6               /* Octets in one ethernet addr  */
-
 #define __verify_pcpu_ptr(ptr)                                         \
 do {                                                                   \
        const void __percpu *__vpp_verify = (typeof((ptr) + 0))NULL;    \
@@ -66,15 +66,12 @@ do {                                                                        \
 #define NET_SKB_PAD    max(32, MVPP2_CPU_D_CACHE_LINE_SIZE)
 
 #define CONFIG_NR_CPUS         1
-#define ETH_HLEN               ETHER_HDR_SIZE  /* Total octets in header */
 
 /* 2(HW hdr) 14(MAC hdr) 4(CRC) 32(extra for cache prefetch) */
 #define WRAP                   (2 + ETH_HLEN + 4 + 32)
 #define MTU                    1500
 #define RX_BUFFER_SIZE         (ALIGN(MTU + WRAP, ARCH_DMA_MINALIGN))
 
-#define MVPP2_SMI_TIMEOUT                      10000
-
 /* RX Fifo Registers */
 #define MVPP2_RX_DATA_FIFO_SIZE_REG(port)      (0x00 + 4 * (port))
 #define MVPP2_RX_ATTR_FIFO_SIZE_REG(port)      (0x20 + 4 * (port))
@@ -314,6 +311,8 @@ do {                                                                        \
 #define            MVPP22_BM_ADDR_HIGH_VIRT_RLS_MASK   0xff00
 #define     MVPP22_BM_ADDR_HIGH_VIRT_RLS_SHIFT 8
 #define MVPP22_BM_MC_RLS_REG                   0x64d4
+#define MVPP22_BM_POOL_BASE_HIGH_REG           0x6310
+#define MVPP22_BM_POOL_BASE_HIGH_MASK          0xff
 
 /* TX Scheduler registers */
 #define MVPP2_TXP_SCHED_PORT_INDEX_REG         0x8000
@@ -442,7 +441,7 @@ do {                                                                        \
 /* MPCS registers */
 
 #define PCS40G_COMMON_CONTROL                  0x14
-#define      FORWARD_ERROR_CORRECTION_MASK     BIT(1)
+#define      FORWARD_ERROR_CORRECTION_MASK     BIT(10)
 
 #define PCS_CLOCK_RESET                                0x14c
 #define      TX_SD_CLK_RESET_MASK              BIT(0)
@@ -499,23 +498,8 @@ do {                                                                       \
 #define MVPP2_QUEUE_NEXT_DESC(q, index) \
        (((index) < (q)->last_desc) ? ((index) + 1) : 0)
 
-/* SMI: 0xc0054 -> offset 0x54 to lms_base */
-#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 */
-#define     MVPP2_SMI_DATA_MASK                        (0xffff << MVPP2_SMI_DATA_OFFS)
-#define     MVPP2_SMI_DEV_ADDR_OFFS            16      /* PHY device address */
-#define     MVPP2_SMI_REG_ADDR_OFFS            21      /* PHY device reg addr*/
-#define     MVPP2_SMI_OPCODE_OFFS              26      /* Write/Read opcode */
-#define     MVPP2_SMI_OPCODE_READ              (1 << MVPP2_SMI_OPCODE_OFFS)
-#define     MVPP2_SMI_READ_VALID               (1 << 27)       /* Read Valid */
-#define     MVPP2_SMI_BUSY                     (1 << 28)       /* Busy */
-
-#define     MVPP2_PHY_ADDR_MASK                        0x1f
-#define     MVPP2_PHY_REG_MASK                 0x1f
 
 /* Additional PPv2.2 offsets */
 #define MVPP22_MPCS                            0x007000
@@ -604,7 +588,7 @@ enum mv_netc_lanes {
 /* Default number of TXQs in use */
 #define MVPP2_DEFAULT_TXQ              1
 
-/* Dfault number of RXQs in use */
+/* Default number of RXQs in use */
 #define MVPP2_DEFAULT_RXQ              1
 #define CONFIG_MV_ETH_RXQ              8       /* increment by 8 */
 
@@ -615,10 +599,10 @@ enum mv_netc_lanes {
 #define MVPP2_MAX_TXD                  16
 
 /* Amount of Tx descriptors that can be reserved at once by CPU */
-#define MVPP2_CPU_DESC_CHUNK           64
+#define MVPP2_CPU_DESC_CHUNK           16
 
 /* Max number of Tx descriptors in each aggregated queue */
-#define MVPP2_AGGR_TXQ_SIZE            256
+#define MVPP2_AGGR_TXQ_SIZE            16
 
 /* Descriptor aligned size */
 #define MVPP2_DESC_ALIGNED_SIZE                32
@@ -906,7 +890,6 @@ struct mvpp2 {
        void __iomem *base;
        void __iomem *lms_base;
        void __iomem *iface_base;
-       void __iomem *mdio_base;
 
        void __iomem *mpcs_base;
        void __iomem *xpcs_base;
@@ -937,9 +920,8 @@ struct mvpp2 {
        /* Maximum number of RXQs per port */
        unsigned int max_port_rxqs;
 
-       struct mii_dev *bus;
-
        int probe_done;
+       u8 num_ports;
 };
 
 struct mvpp2_pcpu_stats {
@@ -983,8 +965,13 @@ struct mvpp2_port {
 
        struct phy_device *phy_dev;
        phy_interface_t phy_interface;
-       int phy_node;
        int phyaddr;
+       struct udevice *mdio_dev;
+       struct mii_dev *bus;
+#if CONFIG_IS_ENABLED(DM_GPIO)
+       struct gpio_desc phy_reset_gpio;
+       struct gpio_desc phy_tx_disable_gpio;
+#endif
        int init;
        unsigned int link;
        unsigned int duplex;
@@ -2587,6 +2574,10 @@ static int mvpp2_bm_pool_create(struct udevice *dev,
 
        mvpp2_write(priv, MVPP2_BM_POOL_BASE_REG(bm_pool->id),
                    lower_32_bits(bm_pool->dma_addr));
+       if (priv->hw_version == MVPP22)
+               mvpp2_write(priv, MVPP22_BM_POOL_BASE_HIGH_REG,
+                           (upper_32_bits(bm_pool->dma_addr) &
+                           MVPP22_BM_POOL_BASE_HIGH_MASK));
        mvpp2_write(priv, MVPP2_BM_POOL_SIZE_REG(bm_pool->id), size);
 
        val = mvpp2_read(priv, MVPP2_BM_POOL_CTRL_REG(bm_pool->id));
@@ -2618,6 +2609,13 @@ static void mvpp2_bm_pool_bufsize_set(struct mvpp2 *priv,
 static void mvpp2_bm_bufs_free(struct udevice *dev, struct mvpp2 *priv,
                               struct mvpp2_bm_pool *bm_pool)
 {
+       int i;
+
+       for (i = 0; i < bm_pool->buf_num; i++) {
+               /* Allocate buffer back from the buffer manager */
+               mvpp2_read(priv, MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));
+       }
+
        bm_pool->buf_num = 0;
 }
 
@@ -2655,7 +2653,7 @@ static int mvpp2_bm_pools_init(struct udevice *dev,
                err = mvpp2_bm_pool_create(dev, priv, bm_pool, size);
                if (err)
                        goto err_unroll_pools;
-               mvpp2_bm_pool_bufsize_set(priv, bm_pool, 0);
+               mvpp2_bm_pool_bufsize_set(priv, bm_pool, RX_BUFFER_SIZE);
        }
        return 0;
 
@@ -2841,9 +2839,6 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
                }
        }
 
-       mvpp2_bm_pool_bufsize_set(port->priv, new_pool,
-                                 MVPP2_RX_BUF_SIZE(new_pool->pkt_size));
-
        return new_pool;
 }
 
@@ -3050,10 +3045,6 @@ static void gop_gmac_sgmii2_5_cfg(struct mvpp2_port *port)
        val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
        writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
 
-       val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
-       val |= MVPP2_GMAC_PORT_DIS_PADING_MASK;
-       writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
-
        val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
        /*
         * Configure GIG MAC to 1000Base-X mode connected to a fiber
@@ -3096,10 +3087,6 @@ static void gop_gmac_sgmii_cfg(struct mvpp2_port *port)
        val |= MVPP2_GMAC_CTRL4_QSGMII_BYPASS_ACTIVE_MASK;
        writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
 
-       val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
-       val |= MVPP2_GMAC_PORT_DIS_PADING_MASK;
-       writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
-
        val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
        /* configure GIG MAC to SGMII mode */
        val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
@@ -3138,10 +3125,6 @@ static void gop_gmac_rgmii_cfg(struct mvpp2_port *port)
        val |= MVPP2_GMAC_CTRL4_EXT_PIN_GMII_SEL_MASK;
        writel(val, port->base + MVPP2_GMAC_CTRL_4_REG);
 
-       val = readl(port->base + MVPP2_GMAC_CTRL_2_REG);
-       val &= ~MVPP2_GMAC_PORT_DIS_PADING_MASK;
-       writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
-
        val = readl(port->base + MVPP2_GMAC_CTRL_0_REG);
        /* configure GIG MAC to SGMII mode */
        val &= ~MVPP2_GMAC_PORT_TYPE_MASK;
@@ -3244,7 +3227,7 @@ static int gop_xpcs_mode(struct mvpp2_port *port, int num_of_lanes)
 
        /* configure XG MAC mode */
        val = readl(port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
-       val &= ~MVPP22_XPCS_PCSMODE_OFFS;
+       val &= ~MVPP22_XPCS_PCSMODE_MASK;
        val &= ~MVPP22_XPCS_LANEACTIVE_MASK;
        val |= (2 * lane) << MVPP22_XPCS_LANEACTIVE_OFFS;
        writel(val, port->priv->xpcs_base + MVPP22_XPCS_GLOBAL_CFG_0_REG);
@@ -4472,7 +4455,15 @@ static int mvpp2_rx_refill(struct mvpp2_port *port,
 /* Set hw internals when starting port */
 static void mvpp2_start_dev(struct mvpp2_port *port)
 {
-       mvpp2_gmac_max_rx_size_set(port);
+       switch (port->phy_interface) {
+       case PHY_INTERFACE_MODE_RGMII:
+       case PHY_INTERFACE_MODE_RGMII_ID:
+       case PHY_INTERFACE_MODE_SGMII:
+               mvpp2_gmac_max_rx_size_set(port);
+       default:
+               break;
+       }
+
        mvpp2_txp_max_tx_size_set(port);
 
        if (port->priv->hw_version == MVPP21)
@@ -4495,17 +4486,40 @@ static void mvpp2_stop_dev(struct mvpp2_port *port)
                gop_port_enable(port, 0);
 }
 
-static int mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port)
+static void mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port)
 {
        struct phy_device *phy_dev;
 
        if (!port->init || port->link == 0) {
-               phy_dev = phy_connect(port->priv->bus, port->phyaddr, dev,
-                                     port->phy_interface);
+               phy_dev = dm_mdio_phy_connect(port->mdio_dev, port->phyaddr,
+                                             dev, port->phy_interface);
+
+               /*
+                * If the phy doesn't match with any existing u-boot drivers the
+                * phy framework will connect it to generic one which
+                * uid == 0xffffffff. In this case act as if the phy wouldn't be
+                * declared in dts. Otherwise in case of 3310 (for which the
+                * driver doesn't exist) the link will not be correctly
+                * detected. Removing phy entry from dts in case of 3310 is not
+                * an option because it is required for the phy_fw_down
+                * procedure.
+                */
+               if (phy_dev &&
+                   phy_dev->drv->uid == 0xffffffff) {/* Generic phy */
+                       netdev_warn(port->dev,
+                                   "Marking phy as invalid, link will not be checked\n");
+                       /* set phy_addr to invalid value */
+                       port->phyaddr = PHY_MAX_ADDR;
+                       mvpp2_egress_enable(port);
+                       mvpp2_ingress_enable(port);
+
+                       return;
+               }
+
                port->phy_dev = phy_dev;
                if (!phy_dev) {
                        netdev_err(port->dev, "cannot connect to phy\n");
-                       return -ENODEV;
+                       return;
                }
                phy_dev->supported &= PHY_GBIT_FEATURES;
                phy_dev->advertising = phy_dev->supported;
@@ -4517,18 +4531,14 @@ static int mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port)
 
                phy_config(phy_dev);
                phy_startup(phy_dev);
-               if (!phy_dev->link) {
+               if (!phy_dev->link)
                        printf("%s: No link\n", phy_dev->dev->name);
-                       return -1;
-               }
-
-               port->init = 1;
+               else
+                       port->init = 1;
        } else {
                mvpp2_egress_enable(port);
                mvpp2_ingress_enable(port);
        }
-
-       return 0;
 }
 
 static int mvpp2_open(struct udevice *dev, struct mvpp2_port *port)
@@ -4567,11 +4577,13 @@ static int mvpp2_open(struct udevice *dev, struct mvpp2_port *port)
                return err;
        }
 
-       err = mvpp2_phy_connect(dev, port);
-       if (err < 0)
-               return err;
-
-       mvpp2_link_event(port);
+       if (port->phyaddr < PHY_MAX_ADDR) {
+               mvpp2_phy_connect(dev, port);
+               mvpp2_link_event(port);
+       } else {
+               mvpp2_egress_enable(port);
+               mvpp2_ingress_enable(port);
+       }
 
        mvpp2_start_dev(port);
 
@@ -4666,20 +4678,6 @@ static int mvpp2_port_init(struct udevice *dev, struct mvpp2_port *port)
                port->rxqs[queue] = rxq;
        }
 
-       /* Configure Rx queue group interrupt for this port */
-       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++) {
@@ -4716,13 +4714,27 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port)
        const char *phy_mode_str;
        int phy_node;
        u32 id;
-       u32 phyaddr;
+       u32 phyaddr = 0;
        int phy_mode = -1;
+       int ret;
 
        phy_node = fdtdec_lookup_phandle(gd->fdt_blob, port_node, "phy");
-       if (phy_node < 0) {
-               dev_err(&pdev->dev, "missing phy\n");
-               return -ENODEV;
+
+       if (phy_node > 0) {
+               int parent;
+               phyaddr = fdtdec_get_int(gd->fdt_blob, phy_node, "reg", 0);
+               if (phyaddr < 0) {
+                       dev_err(&pdev->dev, "could not find phy address\n");
+                       return -1;
+               }
+               parent = fdt_parent_offset(gd->fdt_blob, phy_node);
+               ret = uclass_get_device_by_of_offset(UCLASS_MDIO, parent,
+                                                    &port->mdio_dev);
+               if (ret)
+                       return ret;
+       } else {
+               /* phy_addr is set to invalid value */
+               phyaddr = PHY_MAX_ADDR;
        }
 
        phy_mode_str = fdt_getprop(gd->fdt_blob, port_node, "phy-mode", NULL);
@@ -4739,6 +4751,13 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port)
                return -EINVAL;
        }
 
+#if CONFIG_IS_ENABLED(DM_GPIO)
+       gpio_request_by_name(dev, "phy-reset-gpios", 0,
+                            &port->phy_reset_gpio, GPIOD_IS_OUT);
+       gpio_request_by_name(dev, "marvell,sfp-tx-disable-gpio", 0,
+                            &port->phy_tx_disable_gpio, GPIOD_IS_OUT);
+#endif
+
        /*
         * ToDo:
         * Not sure if this DT property "phy-speed" will get accepted, so
@@ -4748,20 +4767,32 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port)
        port->phy_speed = fdtdec_get_int(gd->fdt_blob, port_node,
                                         "phy-speed", 1000);
 
-       phyaddr = fdtdec_get_int(gd->fdt_blob, phy_node, "reg", 0);
-
        port->id = id;
        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;
 
        return 0;
 }
 
+#if CONFIG_IS_ENABLED(DM_GPIO)
+/* Port GPIO initialization */
+static void mvpp2_gpio_init(struct mvpp2_port *port)
+{
+       if (dm_gpio_is_valid(&port->phy_reset_gpio)) {
+               dm_gpio_set_value(&port->phy_reset_gpio, 1);
+               mdelay(10);
+               dm_gpio_set_value(&port->phy_reset_gpio, 0);
+       }
+
+       if (dm_gpio_is_valid(&port->phy_tx_disable_gpio))
+               dm_gpio_set_value(&port->phy_tx_disable_gpio, 0);
+}
+#endif
+
 /* Ports initialization */
 static int mvpp2_port_probe(struct udevice *dev,
                            struct mvpp2_port *port,
@@ -4780,7 +4811,12 @@ static int mvpp2_port_probe(struct udevice *dev,
        }
        mvpp2_port_power_up(port);
 
+#if CONFIG_IS_ENABLED(DM_GPIO)
+       mvpp2_gpio_init(port);
+#endif
+
        priv->port_list[port->id] = port;
+       priv->num_ports++;
        return 0;
 }
 
@@ -4945,13 +4981,14 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv)
                return -EINVAL;
        }
 
-       /* MBUS windows configuration */
-       dram_target_info = mvebu_mbus_dram_info();
-       if (dram_target_info)
-               mvpp2_conf_mbus_windows(dram_target_info, priv);
-
        if (priv->hw_version == MVPP22)
                mvpp2_axi_init(priv);
+       else {
+               /* MBUS windows configuration */
+               dram_target_info = mvebu_mbus_dram_info();
+               if (dram_target_info)
+                       mvpp2_conf_mbus_windows(dram_target_info, priv);
+       }
 
        if (priv->hw_version == MVPP21) {
                /* Disable HW PHY polling */
@@ -4988,25 +5025,6 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv)
        if (priv->hw_version == MVPP22)
                mvpp2_tx_fifo_init(priv);
 
-       /* Reset Rx queue group interrupt configuration */
-       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;
-
-                       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);
@@ -5030,118 +5048,6 @@ static int mvpp2_init(struct udevice *dev, struct mvpp2 *priv)
        return 0;
 }
 
-/* SMI / MDIO functions */
-
-static int smi_wait_ready(struct mvpp2 *priv)
-{
-       u32 timeout = MVPP2_SMI_TIMEOUT;
-       u32 smi_reg;
-
-       /* wait till the SMI is not busy */
-       do {
-               /* read smi register */
-               smi_reg = readl(priv->mdio_base);
-               if (timeout-- == 0) {
-                       printf("Error: SMI busy timeout\n");
-                       return -EFAULT;
-               }
-       } while (smi_reg & MVPP2_SMI_BUSY);
-
-       return 0;
-}
-
-/*
- * mpp2_mdio_read - miiphy_read callback function.
- *
- * Returns 16bit phy register value, or 0xffff on error
- */
-static int mpp2_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
-{
-       struct mvpp2 *priv = bus->priv;
-       u32 smi_reg;
-       u32 timeout;
-
-       /* check parameters */
-       if (addr > MVPP2_PHY_ADDR_MASK) {
-               printf("Error: Invalid PHY address %d\n", addr);
-               return -EFAULT;
-       }
-
-       if (reg > MVPP2_PHY_REG_MASK) {
-               printf("Err: Invalid register offset %d\n", reg);
-               return -EFAULT;
-       }
-
-       /* wait till the SMI is not busy */
-       if (smi_wait_ready(priv) < 0)
-               return -EFAULT;
-
-       /* fill the phy address and regiser offset and read opcode */
-       smi_reg = (addr << MVPP2_SMI_DEV_ADDR_OFFS)
-               | (reg << MVPP2_SMI_REG_ADDR_OFFS)
-               | MVPP2_SMI_OPCODE_READ;
-
-       /* write the smi register */
-       writel(smi_reg, priv->mdio_base);
-
-       /* wait till read value is ready */
-       timeout = MVPP2_SMI_TIMEOUT;
-
-       do {
-               /* read smi register */
-               smi_reg = readl(priv->mdio_base);
-               if (timeout-- == 0) {
-                       printf("Err: SMI read ready timeout\n");
-                       return -EFAULT;
-               }
-       } while (!(smi_reg & MVPP2_SMI_READ_VALID));
-
-       /* Wait for the data to update in the SMI register */
-       for (timeout = 0; timeout < MVPP2_SMI_TIMEOUT; timeout++)
-               ;
-
-       return readl(priv->mdio_base) & MVPP2_SMI_DATA_MASK;
-}
-
-/*
- * mpp2_mdio_write - miiphy_write callback function.
- *
- * Returns 0 if write succeed, -EINVAL on bad parameters
- * -ETIME on timeout
- */
-static int mpp2_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
-                          u16 value)
-{
-       struct mvpp2 *priv = bus->priv;
-       u32 smi_reg;
-
-       /* check parameters */
-       if (addr > MVPP2_PHY_ADDR_MASK) {
-               printf("Error: Invalid PHY address %d\n", addr);
-               return -EFAULT;
-       }
-
-       if (reg > MVPP2_PHY_REG_MASK) {
-               printf("Err: Invalid register offset %d\n", reg);
-               return -EFAULT;
-       }
-
-       /* wait till the SMI is not busy */
-       if (smi_wait_ready(priv) < 0)
-               return -EFAULT;
-
-       /* fill the phy addr and reg offset and write opcode and data */
-       smi_reg = value << MVPP2_SMI_DATA_OFFS;
-       smi_reg |= (addr << MVPP2_SMI_DEV_ADDR_OFFS)
-               | (reg << MVPP2_SMI_REG_ADDR_OFFS);
-       smi_reg &= ~MVPP2_SMI_OPCODE_READ;
-
-       /* write the smi register */
-       writel(smi_reg, priv->mdio_base);
-
-       return 0;
-}
-
 static int mvpp2_recv(struct udevice *dev, int flags, uchar **packetp)
 {
        struct mvpp2_port *port = dev_get_priv(dev);
@@ -5152,21 +5058,14 @@ static int mvpp2_recv(struct udevice *dev, int flags, uchar **packetp)
        int pool, rx_bytes, err;
        int rx_received;
        struct mvpp2_rx_queue *rxq;
-       u32 cause_rx_tx, cause_rx, cause_misc;
        u8 *data;
 
-       cause_rx_tx = mvpp2_read(port->priv,
-                                MVPP2_ISR_RX_TX_CAUSE_REG(port->id));
-       cause_rx_tx &= ~MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK;
-       cause_misc = cause_rx_tx & MVPP2_CAUSE_MISC_SUM_MASK;
-       if (!cause_rx_tx && !cause_misc)
-               return 0;
-
-       cause_rx = cause_rx_tx & MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK;
+       if (port->phyaddr < PHY_MAX_ADDR)
+               if (!port->phy_dev->link)
+                       return 0;
 
        /* Process RX packets */
-       cause_rx |= port->pending_cause_rx;
-       rxq = mvpp2_get_rx_queue(port, cause_rx);
+       rxq = port->rxqs[0];
 
        /* Get number of received packets and clamp the to-do */
        rx_received = mvpp2_rxq_received(port, rxq->id);
@@ -5222,21 +5121,6 @@ static int mvpp2_recv(struct udevice *dev, int flags, uchar **packetp)
        return rx_bytes;
 }
 
-/* Drain Txq */
-static void mvpp2_txq_drain(struct mvpp2_port *port, struct mvpp2_tx_queue *txq,
-                           int enable)
-{
-       u32 val;
-
-       mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
-       val = mvpp2_read(port->priv, MVPP2_TXQ_PREF_BUF_REG);
-       if (enable)
-               val |= MVPP2_TXQ_DRAIN_EN_MASK;
-       else
-               val &= ~MVPP2_TXQ_DRAIN_EN_MASK;
-       mvpp2_write(port->priv, MVPP2_TXQ_PREF_BUF_REG, val);
-}
-
 static int mvpp2_send(struct udevice *dev, void *packet, int length)
 {
        struct mvpp2_port *port = dev_get_priv(dev);
@@ -5245,6 +5129,10 @@ static int mvpp2_send(struct udevice *dev, void *packet, int length)
        int tx_done;
        int timeout;
 
+       if (port->phyaddr < PHY_MAX_ADDR)
+               if (!port->phy_dev->link)
+                       return 0;
+
        txq = port->txqs[0];
        aggr_txq = &port->priv->aggr_txqs[smp_processor_id()];
 
@@ -5280,9 +5168,6 @@ static int mvpp2_send(struct udevice *dev, void *packet, int length)
                tx_done = mvpp2_txq_pend_desc_num_get(port, txq);
        } while (tx_done);
 
-       /* Enable TXQ drain */
-       mvpp2_txq_drain(port, txq, 1);
-
        timeout = 0;
        do {
                if (timeout++ > 10000) {
@@ -5292,9 +5177,6 @@ static int mvpp2_send(struct udevice *dev, void *packet, int length)
                tx_done = mvpp2_txq_sent_desc_proc(port, txq);
        } while (!tx_done);
 
-       /* Disable TXQ drain */
-       mvpp2_txq_drain(port, txq, 0);
-
        return 0;
 }
 
@@ -5309,7 +5191,14 @@ static int mvpp2_start(struct udevice *dev)
        /* Reconfigure parser accept the original MAC address */
        mvpp2_prs_update_mac_da(port, port->dev_addr);
 
-       mvpp2_port_power_up(port);
+       switch (port->phy_interface) {
+       case PHY_INTERFACE_MODE_RGMII:
+       case PHY_INTERFACE_MODE_RGMII_ID:
+       case PHY_INTERFACE_MODE_SGMII:
+               mvpp2_port_power_up(port);
+       default:
+               break;
+       }
 
        mvpp2_open(dev, port);
 
@@ -5325,6 +5214,13 @@ static void mvpp2_stop(struct udevice *dev)
        mvpp2_cleanup_txqs(port);
 }
 
+static int mvpp2_write_hwaddr(struct udevice *dev)
+{
+       struct mvpp2_port *port = dev_get_priv(dev);
+
+       return mvpp2_prs_update_mac_da(port, port->dev_addr);
+}
+
 static int mvpp22_smi_phy_addr_cfg(struct mvpp2_port *port)
 {
        writel(port->phyaddr, port->priv->iface_base +
@@ -5336,7 +5232,6 @@ static int mvpp22_smi_phy_addr_cfg(struct mvpp2_port *port)
 static int mvpp2_base_probe(struct udevice *dev)
 {
        struct mvpp2 *priv = dev_get_priv(dev);
-       struct mii_dev *bus;
        void *bd_space;
        u32 size = 0;
        int i;
@@ -5387,23 +5282,19 @@ static int mvpp2_base_probe(struct udevice *dev)
        memset(bd_space, 0, size);
 
        /* Save base addresses for later use */
-       priv->base = (void *)dev_get_addr_index(dev, 0);
+       priv->base = (void *)devfdt_get_addr_index(dev, 0);
        if (IS_ERR(priv->base))
                return PTR_ERR(priv->base);
 
        if (priv->hw_version == MVPP21) {
-               priv->lms_base = (void *)dev_get_addr_index(dev, 1);
+               priv->lms_base = (void *)devfdt_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);
+               priv->iface_base = (void *)devfdt_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;
-
                /* Store common base addresses for all ports */
                priv->mpcs_base = priv->iface_base + MVPP22_MPCS;
                priv->xpcs_base = priv->iface_base + MVPP22_XPCS;
@@ -5415,20 +5306,7 @@ static int mvpp2_base_probe(struct udevice *dev)
        else
                priv->max_port_rxqs = 32;
 
-       /* Finally create and register the MDIO bus driver */
-       bus = mdio_alloc();
-       if (!bus) {
-               printf("Failed to allocate MDIO bus\n");
-               return -ENOMEM;
-       }
-
-       bus->read = mpp2_mdio_read;
-       bus->write = mpp2_mdio_write;
-       snprintf(bus->name, sizeof(bus->name), dev->name);
-       bus->priv = (void *)priv;
-       priv->bus = bus;
-
-       return mdio_register(bus);
+       return 0;
 }
 
 static int mvpp2_probe(struct udevice *dev)
@@ -5438,12 +5316,10 @@ static int mvpp2_probe(struct udevice *dev)
        int err;
 
        /* Only call the probe function for the parent once */
-       if (!priv->probe_done) {
+       if (!priv->probe_done)
                err = mvpp2_base_probe(dev->parent);
-               priv->probe_done = 1;
-       }
 
-       port->priv = dev_get_priv(dev->parent);
+       port->priv = priv;
 
        err = phy_info_parse(dev, port);
        if (err)
@@ -5456,7 +5332,7 @@ static int mvpp2_probe(struct udevice *dev)
        if (priv->hw_version == MVPP21) {
                int priv_common_regs_num = 2;
 
-               port->base = (void __iomem *)dev_get_addr_index(
+               port->base = (void __iomem *)devfdt_get_addr_index(
                        dev->parent, priv_common_regs_num + port->id);
                if (IS_ERR(port->base))
                        return PTR_ERR(port->base);
@@ -5472,17 +5348,22 @@ static int mvpp2_probe(struct udevice *dev)
                        port->gop_id * MVPP22_PORT_OFFSET;
 
                /* Set phy address of the port */
-               mvpp22_smi_phy_addr_cfg(port);
+               if (port->phyaddr < PHY_MAX_ADDR)
+                       mvpp22_smi_phy_addr_cfg(port);
 
                /* GoP Init */
                gop_port_init(port);
        }
 
-       /* Initialize network controller */
-       err = mvpp2_init(dev, priv);
-       if (err < 0) {
-               dev_err(&pdev->dev, "failed to initialize controller\n");
-               return err;
+       if (!priv->probe_done) {
+               /* Initialize network controller */
+               err = mvpp2_init(dev, priv);
+               if (err < 0) {
+                       dev_err(&pdev->dev, "failed to initialize controller\n");
+                       return err;
+               }
+               priv->num_ports = 0;
+               priv->probe_done = 1;
        }
 
        err = mvpp2_port_probe(dev, port, dev_of_offset(dev), priv);
@@ -5501,20 +5382,43 @@ static int mvpp2_probe(struct udevice *dev)
        return 0;
 }
 
+/*
+ * Empty BM pool and stop its activity before the OS is started
+ */
+static int mvpp2_remove(struct udevice *dev)
+{
+       struct mvpp2_port *port = dev_get_priv(dev);
+       struct mvpp2 *priv = port->priv;
+       int i;
+
+       priv->num_ports--;
+
+       if (priv->num_ports)
+               return 0;
+
+       for (i = 0; i < MVPP2_BM_POOLS_NUM; i++)
+               mvpp2_bm_pool_destroy(dev, priv, &priv->bm_pools[i]);
+
+       return 0;
+}
+
 static const struct eth_ops mvpp2_ops = {
        .start          = mvpp2_start,
        .send           = mvpp2_send,
        .recv           = mvpp2_recv,
        .stop           = mvpp2_stop,
+       .write_hwaddr   = mvpp2_write_hwaddr
 };
 
 static struct driver mvpp2_driver = {
        .name   = "mvpp2",
        .id     = UCLASS_ETH,
        .probe  = mvpp2_probe,
+       .remove = mvpp2_remove,
        .ops    = &mvpp2_ops,
        .priv_auto_alloc_size = sizeof(struct mvpp2_port),
        .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+       .flags  = DM_FLAG_ACTIVE_DMA,
 };
 
 /*
@@ -5558,6 +5462,10 @@ static int mvpp2_base_bind(struct udevice *parent)
                id += base_id_add;
 
                name = calloc(1, 16);
+               if (!name) {
+                       free(plat);
+                       return -ENOMEM;
+               }
                sprintf(name, "mvpp2-%d", id);
 
                /* Create child device UCLASS_ETH and bind it */