void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt);
 };
 
+struct mac_device_info;
+
 struct stmmac_ops {
        /* MAC core initialization */
-       void (*core_init) (void __iomem *ioaddr, int mtu);
+       void (*core_init)(struct mac_device_info *hw, int mtu);
        /* Enable and verify that the IPC module is supported */
-       int (*rx_ipc) (void __iomem *ioaddr);
+       int (*rx_ipc)(struct mac_device_info *hw);
        /* Dump MAC registers */
-       void (*dump_regs) (void __iomem *ioaddr);
+       void (*dump_regs)(struct mac_device_info *hw);
        /* Handle extra events on specific interrupts hw dependent */
-       int (*host_irq_status) (void __iomem *ioaddr,
-                               struct stmmac_extra_stats *x);
+       int (*host_irq_status)(struct mac_device_info *hw,
+                              struct stmmac_extra_stats *x);
        /* Multicast filter setting */
-       void (*set_filter) (struct net_device *dev, int id);
+       void (*set_filter)(struct net_device *dev, int id);
        /* Flow control setting */
-       void (*flow_ctrl) (void __iomem *ioaddr, unsigned int duplex,
-                          unsigned int fc, unsigned int pause_time);
+       void (*flow_ctrl)(struct mac_device_info *hw, unsigned int duplex,
+                         unsigned int fc, unsigned int pause_time);
        /* Set power management mode (e.g. magic frame) */
-       void (*pmt) (void __iomem *ioaddr, unsigned long mode);
+       void (*pmt)(struct mac_device_info *hw, unsigned long mode);
        /* Set/Get Unicast MAC addresses */
-       void (*set_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
-                              unsigned int reg_n);
-       void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
-                              unsigned int reg_n);
-       void (*set_eee_mode) (void __iomem *ioaddr);
-       void (*reset_eee_mode) (void __iomem *ioaddr);
-       void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw);
-       void (*set_eee_pls) (void __iomem *ioaddr, int link);
-       void (*ctrl_ane) (void __iomem *ioaddr, bool restart);
-       void (*get_adv) (void __iomem *ioaddr, struct rgmii_adv *adv);
+       void (*set_umac_addr)(struct mac_device_info *hw, unsigned char *addr,
+                             unsigned int reg_n);
+       void (*get_umac_addr)(struct mac_device_info *hw, unsigned char *addr,
+                             unsigned int reg_n);
+       void (*set_eee_mode)(struct mac_device_info *hw);
+       void (*reset_eee_mode)(struct mac_device_info *hw);
+       void (*set_eee_timer)(struct mac_device_info *hw, int ls, int tw);
+       void (*set_eee_pls)(struct mac_device_info *hw, int link);
+       void (*ctrl_ane)(struct mac_device_info *hw, bool restart);
+       void (*get_adv)(struct mac_device_info *hw, struct rgmii_adv *adv);
 };
 
 struct stmmac_hwtimestamp {
        struct mii_regs mii;    /* MII register Addresses */
        struct mac_link link;
        unsigned int synopsys_uid;
+       void __iomem *pcsr;     /* vpointer to device CSRs */
 };
 
 struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr);
 
 #include <asm/io.h>
 #include "dwmac1000.h"
 
-static void dwmac1000_core_init(void __iomem *ioaddr, int mtu)
+static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
 {
+       void __iomem *ioaddr = hw->pcsr;
        u32 value = readl(ioaddr + GMAC_CONTROL);
        value |= GMAC_CORE_INIT;
        if (mtu > 1500)
 #endif
 }
 
-static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr)
+static int dwmac1000_rx_ipc_enable(struct mac_device_info *hw)
 {
+       void __iomem *ioaddr = hw->pcsr;
        u32 value = readl(ioaddr + GMAC_CONTROL);
 
        value |= GMAC_CONTROL_IPC;
        return !!(value & GMAC_CONTROL_IPC);
 }
 
-static void dwmac1000_dump_regs(void __iomem *ioaddr)
+static void dwmac1000_dump_regs(struct mac_device_info *hw)
 {
+       void __iomem *ioaddr = hw->pcsr;
        int i;
        pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr);
 
        }
 }
 
-static void dwmac1000_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
+static void dwmac1000_set_umac_addr(struct mac_device_info *hw,
+                                   unsigned char *addr,
                                    unsigned int reg_n)
 {
+       void __iomem *ioaddr = hw->pcsr;
        stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
                            GMAC_ADDR_LOW(reg_n));
 }
 
-static void dwmac1000_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
+static void dwmac1000_get_umac_addr(struct mac_device_info *hw,
+                                   unsigned char *addr,
                                    unsigned int reg_n)
 {
+       void __iomem *ioaddr = hw->pcsr;
        stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
                            GMAC_ADDR_LOW(reg_n));
 }
                struct netdev_hw_addr *ha;
 
                netdev_for_each_uc_addr(ha, dev) {
-                       dwmac1000_set_umac_addr(ioaddr, ha->addr, reg);
+                       stmmac_get_mac_addr(ioaddr, ha->addr,
+                                           GMAC_ADDR_HIGH(reg),
+                                           GMAC_ADDR_LOW(reg));
                        reg++;
                }
        }
                 readl(ioaddr + GMAC_HASH_HIGH), readl(ioaddr + GMAC_HASH_LOW));
 }
 
-static void dwmac1000_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
+
+static void dwmac1000_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,
                                unsigned int fc, unsigned int pause_time)
 {
+       void __iomem *ioaddr = hw->pcsr;
        unsigned int flow = 0;
 
        pr_debug("GMAC Flow-Control:\n");
        writel(flow, ioaddr + GMAC_FLOW_CTRL);
 }
 
-static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
+static void dwmac1000_pmt(struct mac_device_info *hw, unsigned long mode)
 {
+       void __iomem *ioaddr = hw->pcsr;
        unsigned int pmt = 0;
 
        if (mode & WAKE_MAGIC) {
        writel(pmt, ioaddr + GMAC_PMT);
 }
 
-static int dwmac1000_irq_status(void __iomem *ioaddr,
+static int dwmac1000_irq_status(struct mac_device_info *hw,
                                struct stmmac_extra_stats *x)
 {
+       void __iomem *ioaddr = hw->pcsr;
        u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
        int ret = 0;
 
        return ret;
 }
 
-static void dwmac1000_set_eee_mode(void __iomem *ioaddr)
+static void dwmac1000_set_eee_mode(struct mac_device_info *hw)
 {
+       void __iomem *ioaddr = hw->pcsr;
        u32 value;
 
        /* Enable the link status receive on RGMII, SGMII ore SMII
        writel(value, ioaddr + LPI_CTRL_STATUS);
 }
 
-static void dwmac1000_reset_eee_mode(void __iomem *ioaddr)
+static void dwmac1000_reset_eee_mode(struct mac_device_info *hw)
 {
+       void __iomem *ioaddr = hw->pcsr;
        u32 value;
 
        value = readl(ioaddr + LPI_CTRL_STATUS);
        writel(value, ioaddr + LPI_CTRL_STATUS);
 }
 
-static void dwmac1000_set_eee_pls(void __iomem *ioaddr, int link)
+static void dwmac1000_set_eee_pls(struct mac_device_info *hw, int link)
 {
+       void __iomem *ioaddr = hw->pcsr;
        u32 value;
 
        value = readl(ioaddr + LPI_CTRL_STATUS);
        writel(value, ioaddr + LPI_CTRL_STATUS);
 }
 
-static void dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
+static void dwmac1000_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
 {
+       void __iomem *ioaddr = hw->pcsr;
        int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);
 
        /* Program the timers in the LPI timer control register:
        writel(value, ioaddr + LPI_TIMER_CTRL);
 }
 
-static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool restart)
+static void dwmac1000_ctrl_ane(struct mac_device_info *hw, bool restart)
 {
+       void __iomem *ioaddr = hw->pcsr;
        /* auto negotiation enable and External Loopback enable */
        u32 value = GMAC_AN_CTRL_ANE | GMAC_AN_CTRL_ELE;
 
        writel(value, ioaddr + GMAC_AN_CTRL);
 }
 
-static void dwmac1000_get_adv(void __iomem *ioaddr, struct rgmii_adv *adv)
+static void dwmac1000_get_adv(struct mac_device_info *hw, struct rgmii_adv *adv)
 {
+       void __iomem *ioaddr = hw->pcsr;
        u32 value = readl(ioaddr + GMAC_ANE_ADV);
 
        if (value & GMAC_ANE_FD)
        if (!mac)
                return NULL;
 
+       mac->pcsr = ioaddr;
        mac->mac = &dwmac1000_ops;
        mac->dma = &dwmac1000_dma_ops;
 
 
 #include <asm/io.h>
 #include "dwmac100.h"
 
-static void dwmac100_core_init(void __iomem *ioaddr, int mtu)
+static void dwmac100_core_init(struct mac_device_info *hw, int mtu)
 {
+       void __iomem *ioaddr = hw->pcsr;
        u32 value = readl(ioaddr + MAC_CONTROL);
 
        writel((value | MAC_CORE_INIT), ioaddr + MAC_CONTROL);
 #endif
 }
 
-static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
+static void dwmac100_dump_mac_regs(struct mac_device_info *hw)
 {
+       void __iomem *ioaddr = hw->pcsr;
        pr_info("\t----------------------------------------------\n"
                "\t  DWMAC 100 CSR (base addr = 0x%p)\n"
                "\t----------------------------------------------\n", ioaddr);
                readl(ioaddr + MAC_VLAN2));
 }
 
-static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
+static int dwmac100_rx_ipc_enable(struct mac_device_info *hw)
 {
        return 0;
 }
 
-static int dwmac100_irq_status(void __iomem *ioaddr,
+static int dwmac100_irq_status(struct mac_device_info *hw,
                               struct stmmac_extra_stats *x)
 {
        return 0;
 }
 
-static void dwmac100_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
+static void dwmac100_set_umac_addr(struct mac_device_info *hw,
+                                  unsigned char *addr,
                                   unsigned int reg_n)
 {
+       void __iomem *ioaddr = hw->pcsr;
        stmmac_set_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
 }
 
-static void dwmac100_get_umac_addr(void __iomem *ioaddr, unsigned char *addr,
+static void dwmac100_get_umac_addr(struct mac_device_info *hw,
+                                  unsigned char *addr,
                                   unsigned int reg_n)
 {
+       void __iomem *ioaddr = hw->pcsr;
        stmmac_get_mac_addr(ioaddr, addr, MAC_ADDR_HIGH, MAC_ADDR_LOW);
 }
 
        writel(value, ioaddr + MAC_CONTROL);
 }
 
-static void dwmac100_flow_ctrl(void __iomem *ioaddr, unsigned int duplex,
+static void dwmac100_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,
                               unsigned int fc, unsigned int pause_time)
 {
+       void __iomem *ioaddr = hw->pcsr;
        unsigned int flow = MAC_FLOW_CTRL_ENABLE;
 
        if (duplex)
 }
 
 /* No PMT module supported on ST boards with this Eth chip. */
-static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
+static void dwmac100_pmt(struct mac_device_info *hw, unsigned long mode)
 {
        return;
 }
 
        pr_info("\tDWMAC100\n");
 
+       mac->pcsr = ioaddr;
        mac->mac = &dwmac100_ops;
        mac->dma = &dwmac100_dma_ops;
 
 
 
                /* Get and convert ADV/LP_ADV from the HW AN registers */
                if (priv->hw->mac->get_adv)
-                       priv->hw->mac->get_adv(priv->ioaddr, &adv);
+                       priv->hw->mac->get_adv(priv->hw, &adv);
                else
                        return -EOPNOTSUPP;     /* should never happen indeed */
 
 
                        spin_lock(&priv->lock);
                        if (priv->hw->mac->ctrl_ane)
-                               priv->hw->mac->ctrl_ane(priv->ioaddr, 1);
+                               priv->hw->mac->ctrl_ane(priv->hw, 1);
                        spin_unlock(&priv->lock);
                }
 
                if (netif_running(netdev))
                        ret = phy_start_aneg(phy);
        } else
-               priv->hw->mac->flow_ctrl(priv->ioaddr, phy->duplex,
+               priv->hw->mac->flow_ctrl(priv->hw, phy->duplex,
                                         priv->flow_ctrl, priv->pause);
        return ret;
 }
 
        /* Check and enter in LPI mode */
        if ((priv->dirty_tx == priv->cur_tx) &&
            (priv->tx_path_in_lpi_mode == false))
-               priv->hw->mac->set_eee_mode(priv->ioaddr);
+               priv->hw->mac->set_eee_mode(priv->hw);
 }
 
 /**
  */
 void stmmac_disable_eee_mode(struct stmmac_priv *priv)
 {
-       priv->hw->mac->reset_eee_mode(priv->ioaddr);
+       priv->hw->mac->reset_eee_mode(priv->hw);
        del_timer_sync(&priv->eee_ctrl_timer);
        priv->tx_path_in_lpi_mode = false;
 }
                        if (priv->eee_active) {
                                pr_debug("stmmac: disable EEE\n");
                                del_timer_sync(&priv->eee_ctrl_timer);
-                               priv->hw->mac->set_eee_timer(priv->ioaddr, 0,
+                               priv->hw->mac->set_eee_timer(priv->hw, 0,
                                                             tx_lpi_timer);
                        }
                        priv->eee_active = 0;
                        priv->eee_ctrl_timer.expires = STMMAC_LPI_T(eee_timer);
                        add_timer(&priv->eee_ctrl_timer);
 
-                       priv->hw->mac->set_eee_timer(priv->ioaddr,
+                       priv->hw->mac->set_eee_timer(priv->hw,
                                                     STMMAC_DEFAULT_LIT_LS,
                                                     tx_lpi_timer);
                } else
                        /* Set HW EEE according to the speed */
-                       priv->hw->mac->set_eee_pls(priv->ioaddr,
+                       priv->hw->mac->set_eee_pls(priv->hw,
                                                   priv->phydev->link);
 
                pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
                }
                /* Flow Control operation */
                if (phydev->pause)
-                       priv->hw->mac->flow_ctrl(priv->ioaddr, phydev->duplex,
+                       priv->hw->mac->flow_ctrl(priv->hw, phydev->duplex,
                                                 fc, pause_time);
 
                if (phydev->speed != priv->speed) {
 static void stmmac_check_ether_addr(struct stmmac_priv *priv)
 {
        if (!is_valid_ether_addr(priv->dev->dev_addr)) {
-               priv->hw->mac->get_umac_addr((void __iomem *)
-                                            priv->dev->base_addr,
+               priv->hw->mac->get_umac_addr(priv->hw,
                                             priv->dev->dev_addr, 0);
                if (!is_valid_ether_addr(priv->dev->dev_addr))
                        eth_hw_addr_random(priv->dev);
        }
 
        /* Copy the MAC addr into the HW  */
-       priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
+       priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0);
 
        /* If required, perform hw setup of the bus. */
        if (priv->plat->bus_setup)
                priv->plat->bus_setup(priv->ioaddr);
 
        /* Initialize the MAC Core */
-       priv->hw->mac->core_init(priv->ioaddr, dev->mtu);
+       priv->hw->mac->core_init(priv->hw, dev->mtu);
 
        /* Enable the MAC Rx/Tx */
        stmmac_set_mac(priv->ioaddr, true);
 
        /* Dump DMA/MAC registers */
        if (netif_msg_hw(priv)) {
-               priv->hw->mac->dump_regs(priv->ioaddr);
+               priv->hw->mac->dump_regs(priv->hw);
                priv->hw->dma->dump_regs(priv->ioaddr);
        }
        priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
        }
 
        if (priv->pcs && priv->hw->mac->ctrl_ane)
-               priv->hw->mac->ctrl_ane(priv->ioaddr, 0);
+               priv->hw->mac->ctrl_ane(priv->hw, 0);
 
        return 0;
 }
 
        /* To handle GMAC own interrupts */
        if (priv->plat->has_gmac) {
-               int status = priv->hw->mac->host_irq_status((void __iomem *)
-                                                           dev->base_addr,
+               int status = priv->hw->mac->host_irq_status(priv->hw,
                                                            &priv->xstats);
                if (unlikely(status)) {
                        /* For LPI we need to save the tx status */
        /* To use alternate (extended) or normal descriptor structures */
        stmmac_selec_desc_mode(priv);
 
-       ret = priv->hw->mac->rx_ipc(priv->ioaddr);
+       ret = priv->hw->mac->rx_ipc(priv->hw);
        if (!ret) {
                pr_warn(" RX IPC Checksum Offload not configured.\n");
                priv->plat->rx_coe = STMMAC_RX_COE_NONE;
 
        /* Enable Power down mode by programming the PMT regs */
        if (device_may_wakeup(priv->device)) {
-               priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
+               priv->hw->mac->pmt(priv->hw, priv->wolopts);
                priv->irq_wake = 1;
        } else {
                stmmac_set_mac(priv->ioaddr, false);
         * from another devices (e.g. serial console).
         */
        if (device_may_wakeup(priv->device)) {
-               priv->hw->mac->pmt(priv->ioaddr, 0);
+               priv->hw->mac->pmt(priv->hw, 0);
                priv->irq_wake = 0;
        } else {
                pinctrl_pm_select_default_state(priv->device);