Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / renesas / sh_eth.c
index 6ed333fe5c04cd36618c465c0a3bec8dafbe8fcc..b8e52cd1a6985cf1c0fd00fe940907fd1bb92e6a 100644 (file)
@@ -2,7 +2,8 @@
  *  SuperH Ethernet device driver
  *
  *  Copyright (C) 2006-2012 Nobuhiro Iwamatsu
- *  Copyright (C) 2008-2012 Renesas Solutions Corp.
+ *  Copyright (C) 2008-2013 Renesas Solutions Corp.
+ *  Copyright (C) 2013 Cogent Embedded, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms and conditions of the GNU General Public License,
                NETIF_MSG_RX_ERR| \
                NETIF_MSG_TX_ERR)
 
+static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
+       [EDSR]          = 0x0000,
+       [EDMR]          = 0x0400,
+       [EDTRR]         = 0x0408,
+       [EDRRR]         = 0x0410,
+       [EESR]          = 0x0428,
+       [EESIPR]        = 0x0430,
+       [TDLAR]         = 0x0010,
+       [TDFAR]         = 0x0014,
+       [TDFXR]         = 0x0018,
+       [TDFFR]         = 0x001c,
+       [RDLAR]         = 0x0030,
+       [RDFAR]         = 0x0034,
+       [RDFXR]         = 0x0038,
+       [RDFFR]         = 0x003c,
+       [TRSCER]        = 0x0438,
+       [RMFCR]         = 0x0440,
+       [TFTR]          = 0x0448,
+       [FDR]           = 0x0450,
+       [RMCR]          = 0x0458,
+       [RPADIR]        = 0x0460,
+       [FCFTR]         = 0x0468,
+       [CSMR]          = 0x04E4,
+
+       [ECMR]          = 0x0500,
+       [ECSR]          = 0x0510,
+       [ECSIPR]        = 0x0518,
+       [PIR]           = 0x0520,
+       [PSR]           = 0x0528,
+       [PIPR]          = 0x052c,
+       [RFLR]          = 0x0508,
+       [APR]           = 0x0554,
+       [MPR]           = 0x0558,
+       [PFTCR]         = 0x055c,
+       [PFRCR]         = 0x0560,
+       [TPAUSER]       = 0x0564,
+       [GECMR]         = 0x05b0,
+       [BCULR]         = 0x05b4,
+       [MAHR]          = 0x05c0,
+       [MALR]          = 0x05c8,
+       [TROCR]         = 0x0700,
+       [CDCR]          = 0x0708,
+       [LCCR]          = 0x0710,
+       [CEFCR]         = 0x0740,
+       [FRECR]         = 0x0748,
+       [TSFRCR]        = 0x0750,
+       [TLFRCR]        = 0x0758,
+       [RFCR]          = 0x0760,
+       [CERCR]         = 0x0768,
+       [CEECR]         = 0x0770,
+       [MAFCR]         = 0x0778,
+       [RMII_MII]      = 0x0790,
+
+       [ARSTR]         = 0x0000,
+       [TSU_CTRST]     = 0x0004,
+       [TSU_FWEN0]     = 0x0010,
+       [TSU_FWEN1]     = 0x0014,
+       [TSU_FCM]       = 0x0018,
+       [TSU_BSYSL0]    = 0x0020,
+       [TSU_BSYSL1]    = 0x0024,
+       [TSU_PRISL0]    = 0x0028,
+       [TSU_PRISL1]    = 0x002c,
+       [TSU_FWSL0]     = 0x0030,
+       [TSU_FWSL1]     = 0x0034,
+       [TSU_FWSLC]     = 0x0038,
+       [TSU_QTAG0]     = 0x0040,
+       [TSU_QTAG1]     = 0x0044,
+       [TSU_FWSR]      = 0x0050,
+       [TSU_FWINMK]    = 0x0054,
+       [TSU_ADQT0]     = 0x0048,
+       [TSU_ADQT1]     = 0x004c,
+       [TSU_VTAG0]     = 0x0058,
+       [TSU_VTAG1]     = 0x005c,
+       [TSU_ADSBSY]    = 0x0060,
+       [TSU_TEN]       = 0x0064,
+       [TSU_POST1]     = 0x0070,
+       [TSU_POST2]     = 0x0074,
+       [TSU_POST3]     = 0x0078,
+       [TSU_POST4]     = 0x007c,
+       [TSU_ADRH0]     = 0x0100,
+       [TSU_ADRL0]     = 0x0104,
+       [TSU_ADRH31]    = 0x01f8,
+       [TSU_ADRL31]    = 0x01fc,
+
+       [TXNLCR0]       = 0x0080,
+       [TXALCR0]       = 0x0084,
+       [RXNLCR0]       = 0x0088,
+       [RXALCR0]       = 0x008c,
+       [FWNLCR0]       = 0x0090,
+       [FWALCR0]       = 0x0094,
+       [TXNLCR1]       = 0x00a0,
+       [TXALCR1]       = 0x00a0,
+       [RXNLCR1]       = 0x00a8,
+       [RXALCR1]       = 0x00ac,
+       [FWNLCR1]       = 0x00b0,
+       [FWALCR1]       = 0x00b4,
+};
+
+static const u16 sh_eth_offset_fast_rcar[SH_ETH_MAX_REGISTER_OFFSET] = {
+       [ECMR]          = 0x0300,
+       [RFLR]          = 0x0308,
+       [ECSR]          = 0x0310,
+       [ECSIPR]        = 0x0318,
+       [PIR]           = 0x0320,
+       [PSR]           = 0x0328,
+       [RDMLR]         = 0x0340,
+       [IPGR]          = 0x0350,
+       [APR]           = 0x0354,
+       [MPR]           = 0x0358,
+       [RFCF]          = 0x0360,
+       [TPAUSER]       = 0x0364,
+       [TPAUSECR]      = 0x0368,
+       [MAHR]          = 0x03c0,
+       [MALR]          = 0x03c8,
+       [TROCR]         = 0x03d0,
+       [CDCR]          = 0x03d4,
+       [LCCR]          = 0x03d8,
+       [CNDCR]         = 0x03dc,
+       [CEFCR]         = 0x03e4,
+       [FRECR]         = 0x03e8,
+       [TSFRCR]        = 0x03ec,
+       [TLFRCR]        = 0x03f0,
+       [RFCR]          = 0x03f4,
+       [MAFCR]         = 0x03f8,
+
+       [EDMR]          = 0x0200,
+       [EDTRR]         = 0x0208,
+       [EDRRR]         = 0x0210,
+       [TDLAR]         = 0x0218,
+       [RDLAR]         = 0x0220,
+       [EESR]          = 0x0228,
+       [EESIPR]        = 0x0230,
+       [TRSCER]        = 0x0238,
+       [RMFCR]         = 0x0240,
+       [TFTR]          = 0x0248,
+       [FDR]           = 0x0250,
+       [RMCR]          = 0x0258,
+       [TFUCR]         = 0x0264,
+       [RFOCR]         = 0x0268,
+       [FCFTR]         = 0x0270,
+       [TRIMD]         = 0x027c,
+};
+
+static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
+       [ECMR]          = 0x0100,
+       [RFLR]          = 0x0108,
+       [ECSR]          = 0x0110,
+       [ECSIPR]        = 0x0118,
+       [PIR]           = 0x0120,
+       [PSR]           = 0x0128,
+       [RDMLR]         = 0x0140,
+       [IPGR]          = 0x0150,
+       [APR]           = 0x0154,
+       [MPR]           = 0x0158,
+       [TPAUSER]       = 0x0164,
+       [RFCF]          = 0x0160,
+       [TPAUSECR]      = 0x0168,
+       [BCFRR]         = 0x016c,
+       [MAHR]          = 0x01c0,
+       [MALR]          = 0x01c8,
+       [TROCR]         = 0x01d0,
+       [CDCR]          = 0x01d4,
+       [LCCR]          = 0x01d8,
+       [CNDCR]         = 0x01dc,
+       [CEFCR]         = 0x01e4,
+       [FRECR]         = 0x01e8,
+       [TSFRCR]        = 0x01ec,
+       [TLFRCR]        = 0x01f0,
+       [RFCR]          = 0x01f4,
+       [MAFCR]         = 0x01f8,
+       [RTRATE]        = 0x01fc,
+
+       [EDMR]          = 0x0000,
+       [EDTRR]         = 0x0008,
+       [EDRRR]         = 0x0010,
+       [TDLAR]         = 0x0018,
+       [RDLAR]         = 0x0020,
+       [EESR]          = 0x0028,
+       [EESIPR]        = 0x0030,
+       [TRSCER]        = 0x0038,
+       [RMFCR]         = 0x0040,
+       [TFTR]          = 0x0048,
+       [FDR]           = 0x0050,
+       [RMCR]          = 0x0058,
+       [TFUCR]         = 0x0064,
+       [RFOCR]         = 0x0068,
+       [FCFTR]         = 0x0070,
+       [RPADIR]        = 0x0078,
+       [TRIMD]         = 0x007c,
+       [RBWAR]         = 0x00c8,
+       [RDFAR]         = 0x00cc,
+       [TBRAR]         = 0x00d4,
+       [TDFAR]         = 0x00d8,
+};
+
+static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
+       [ECMR]          = 0x0160,
+       [ECSR]          = 0x0164,
+       [ECSIPR]        = 0x0168,
+       [PIR]           = 0x016c,
+       [MAHR]          = 0x0170,
+       [MALR]          = 0x0174,
+       [RFLR]          = 0x0178,
+       [PSR]           = 0x017c,
+       [TROCR]         = 0x0180,
+       [CDCR]          = 0x0184,
+       [LCCR]          = 0x0188,
+       [CNDCR]         = 0x018c,
+       [CEFCR]         = 0x0194,
+       [FRECR]         = 0x0198,
+       [TSFRCR]        = 0x019c,
+       [TLFRCR]        = 0x01a0,
+       [RFCR]          = 0x01a4,
+       [MAFCR]         = 0x01a8,
+       [IPGR]          = 0x01b4,
+       [APR]           = 0x01b8,
+       [MPR]           = 0x01bc,
+       [TPAUSER]       = 0x01c4,
+       [BCFR]          = 0x01cc,
+
+       [ARSTR]         = 0x0000,
+       [TSU_CTRST]     = 0x0004,
+       [TSU_FWEN0]     = 0x0010,
+       [TSU_FWEN1]     = 0x0014,
+       [TSU_FCM]       = 0x0018,
+       [TSU_BSYSL0]    = 0x0020,
+       [TSU_BSYSL1]    = 0x0024,
+       [TSU_PRISL0]    = 0x0028,
+       [TSU_PRISL1]    = 0x002c,
+       [TSU_FWSL0]     = 0x0030,
+       [TSU_FWSL1]     = 0x0034,
+       [TSU_FWSLC]     = 0x0038,
+       [TSU_QTAGM0]    = 0x0040,
+       [TSU_QTAGM1]    = 0x0044,
+       [TSU_ADQT0]     = 0x0048,
+       [TSU_ADQT1]     = 0x004c,
+       [TSU_FWSR]      = 0x0050,
+       [TSU_FWINMK]    = 0x0054,
+       [TSU_ADSBSY]    = 0x0060,
+       [TSU_TEN]       = 0x0064,
+       [TSU_POST1]     = 0x0070,
+       [TSU_POST2]     = 0x0074,
+       [TSU_POST3]     = 0x0078,
+       [TSU_POST4]     = 0x007c,
+
+       [TXNLCR0]       = 0x0080,
+       [TXALCR0]       = 0x0084,
+       [RXNLCR0]       = 0x0088,
+       [RXALCR0]       = 0x008c,
+       [FWNLCR0]       = 0x0090,
+       [FWALCR0]       = 0x0094,
+       [TXNLCR1]       = 0x00a0,
+       [TXALCR1]       = 0x00a0,
+       [RXNLCR1]       = 0x00a8,
+       [RXALCR1]       = 0x00ac,
+       [FWNLCR1]       = 0x00b0,
+       [FWALCR1]       = 0x00b4,
+
+       [TSU_ADRH0]     = 0x0100,
+       [TSU_ADRL0]     = 0x0104,
+       [TSU_ADRL31]    = 0x01fc,
+};
+
 #if defined(CONFIG_CPU_SUBTYPE_SH7734) || \
        defined(CONFIG_CPU_SUBTYPE_SH7763) || \
        defined(CONFIG_ARCH_R8A7740)
@@ -78,7 +342,7 @@ static void sh_eth_select_mii(struct net_device *ndev)
 #endif
 
 /* There is CPU dependent code */
-#if defined(CONFIG_CPU_SUBTYPE_SH7724) || defined(CONFIG_ARCH_R8A7779)
+#if defined(CONFIG_ARCH_R8A7779)
 #define SH_ETH_RESET_DEFAULT   1
 static void sh_eth_set_duplex(struct net_device *ndev)
 {
@@ -93,18 +357,60 @@ static void sh_eth_set_duplex(struct net_device *ndev)
 static void sh_eth_set_rate(struct net_device *ndev)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
-       unsigned int bits = ECMR_RTM;
 
-#if defined(CONFIG_ARCH_R8A7779)
-       bits |= ECMR_ELB;
-#endif
+       switch (mdp->speed) {
+       case 10: /* 10BASE */
+               sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_ELB, ECMR);
+               break;
+       case 100:/* 100BASE */
+               sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_ELB, ECMR);
+               break;
+       default:
+               break;
+       }
+}
+
+/* R8A7779 */
+static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
+       .set_duplex     = sh_eth_set_duplex,
+       .set_rate       = sh_eth_set_rate,
+
+       .ecsr_value     = ECSR_PSRTO | ECSR_LCHNG | ECSR_ICD,
+       .ecsipr_value   = ECSIPR_PSRTOIP | ECSIPR_LCHNGIP | ECSIPR_ICDIP,
+       .eesipr_value   = 0x01ff009f,
+
+       .tx_check       = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
+       .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE |
+                         EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI,
+       .tx_error_check = EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE,
+
+       .apr            = 1,
+       .mpr            = 1,
+       .tpauser        = 1,
+       .hw_swap        = 1,
+};
+#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define SH_ETH_RESET_DEFAULT   1
+static void sh_eth_set_duplex(struct net_device *ndev)
+{
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+
+       if (mdp->duplex) /* Full */
+               sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
+       else            /* Half */
+               sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
+}
+
+static void sh_eth_set_rate(struct net_device *ndev)
+{
+       struct sh_eth_private *mdp = netdev_priv(ndev);
 
        switch (mdp->speed) {
        case 10: /* 10BASE */
-               sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~bits, ECMR);
+               sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR);
                break;
        case 100:/* 100BASE */
-               sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | bits, ECMR);
+               sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR);
                break;
        default:
                break;
@@ -592,7 +898,7 @@ static int sh_eth_check_reset(struct net_device *ndev)
                cnt--;
        }
        if (cnt < 0) {
-               printk(KERN_ERR "Device reset fail\n");
+               pr_err("Device reset fail\n");
                ret = -ETIMEDOUT;
        }
        return ret;
@@ -908,11 +1214,8 @@ static int sh_eth_ring_init(struct net_device *ndev)
        /* Allocate all Rx descriptors. */
        rx_ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring;
        mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma,
-                       GFP_KERNEL);
-
+                                         GFP_KERNEL);
        if (!mdp->rx_ring) {
-               dev_err(&ndev->dev, "Cannot allocate Rx Ring (size %d bytes)\n",
-                       rx_ringsize);
                ret = -ENOMEM;
                goto desc_ring_free;
        }
@@ -922,10 +1225,8 @@ static int sh_eth_ring_init(struct net_device *ndev)
        /* Allocate all Tx descriptors. */
        tx_ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring;
        mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma,
-                       GFP_KERNEL);
+                                         GFP_KERNEL);
        if (!mdp->tx_ring) {
-               dev_err(&ndev->dev, "Cannot allocate Tx Ring (size %d bytes)\n",
-                       tx_ringsize);
                ret = -ENOMEM;
                goto desc_ring_free;
        }
@@ -2147,7 +2448,8 @@ static int sh_eth_get_vtag_index(struct sh_eth_private *mdp)
                return TSU_VTAG1;
 }
 
-static int sh_eth_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
+static int sh_eth_vlan_rx_add_vid(struct net_device *ndev,
+                                 __be16 proto, u16 vid)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        int vtag_reg_index = sh_eth_get_vtag_index(mdp);
@@ -2177,7 +2479,8 @@ static int sh_eth_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
        return 0;
 }
 
-static int sh_eth_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
+static int sh_eth_vlan_rx_kill_vid(struct net_device *ndev,
+                                  __be16 proto, u16 vid)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        int vtag_reg_index = sh_eth_get_vtag_index(mdp);
@@ -2228,7 +2531,6 @@ static void sh_eth_tsu_init(struct sh_eth_private *mdp)
 /* MDIO bus release function */
 static int sh_mdio_release(struct net_device *ndev)
 {
-       struct sh_eth_private *mdp = netdev_priv(ndev);
        struct mii_bus *bus = dev_get_drvdata(&ndev->dev);
 
        /* unregister mdio bus */
@@ -2237,15 +2539,9 @@ static int sh_mdio_release(struct net_device *ndev)
        /* remove mdio bus info from net_device */
        dev_set_drvdata(&ndev->dev, NULL);
 
-       /* free interrupts memory */
-       kfree(bus->irq);
-
        /* free bitbang info */
        free_mdio_bitbang(bus);
 
-       /* free bitbang memory */
-       kfree(mdp->bitbang);
-
        return 0;
 }
 
@@ -2258,7 +2554,8 @@ static int sh_mdio_init(struct net_device *ndev, int id,
        struct sh_eth_private *mdp = netdev_priv(ndev);
 
        /* create bit control struct for PHY */
-       bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
+       bitbang = devm_kzalloc(&ndev->dev, sizeof(struct bb_info),
+                              GFP_KERNEL);
        if (!bitbang) {
                ret = -ENOMEM;
                goto out;
@@ -2267,18 +2564,17 @@ static int sh_mdio_init(struct net_device *ndev, int id,
        /* bitbang init */
        bitbang->addr = mdp->addr + mdp->reg_offset[PIR];
        bitbang->set_gate = pd->set_mdio_gate;
-       bitbang->mdi_msk = 0x08;
-       bitbang->mdo_msk = 0x04;
-       bitbang->mmd_msk = 0x02;/* MMD */
-       bitbang->mdc_msk = 0x01;
+       bitbang->mdi_msk = PIR_MDI;
+       bitbang->mdo_msk = PIR_MDO;
+       bitbang->mmd_msk = PIR_MMD;
+       bitbang->mdc_msk = PIR_MDC;
        bitbang->ctrl.ops = &bb_ops;
 
        /* MII controller setting */
-       mdp->bitbang = bitbang;
        mdp->mii_bus = alloc_mdio_bitbang(&bitbang->ctrl);
        if (!mdp->mii_bus) {
                ret = -ENOMEM;
-               goto out_free_bitbang;
+               goto out;
        }
 
        /* Hook up MII support for ethtool */
@@ -2288,7 +2584,9 @@ static int sh_mdio_init(struct net_device *ndev, int id,
                mdp->pdev->name, id);
 
        /* PHY IRQ */
-       mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+       mdp->mii_bus->irq = devm_kzalloc(&ndev->dev,
+                                        sizeof(int) * PHY_MAX_ADDR,
+                                        GFP_KERNEL);
        if (!mdp->mii_bus->irq) {
                ret = -ENOMEM;
                goto out_free_bus;
@@ -2300,21 +2598,15 @@ static int sh_mdio_init(struct net_device *ndev, int id,
        /* register mdio bus */
        ret = mdiobus_register(mdp->mii_bus);
        if (ret)
-               goto out_free_irq;
+               goto out_free_bus;
 
        dev_set_drvdata(&ndev->dev, mdp->mii_bus);
 
        return 0;
 
-out_free_irq:
-       kfree(mdp->mii_bus->irq);
-
 out_free_bus:
        free_mdio_bitbang(mdp->mii_bus);
 
-out_free_bitbang:
-       kfree(bitbang);
-
 out:
        return ret;
 }
@@ -2327,6 +2619,9 @@ static const u16 *sh_eth_get_register_offset(int register_type)
        case SH_ETH_REG_GIGABIT:
                reg_offset = sh_eth_offset_gigabit;
                break;
+       case SH_ETH_REG_FAST_RCAR:
+               reg_offset = sh_eth_offset_fast_rcar;
+               break;
        case SH_ETH_REG_FAST_SH4:
                reg_offset = sh_eth_offset_fast_sh4;
                break;
@@ -2334,7 +2629,7 @@ static const u16 *sh_eth_get_register_offset(int register_type)
                reg_offset = sh_eth_offset_fast_sh3_sh2;
                break;
        default:
-               printk(KERN_ERR "Unknown register type (%d)\n", register_type);
+               pr_err("Unknown register type (%d)\n", register_type);
                break;
        }
 
@@ -2364,7 +2659,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
        struct resource *res;
        struct net_device *ndev = NULL;
        struct sh_eth_private *mdp = NULL;
-       struct sh_eth_plat_data *pd;
+       struct sh_eth_plat_data *pd = pdev->dev.platform_data;
 
        /* get base addr */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -2402,10 +2697,9 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
        mdp = netdev_priv(ndev);
        mdp->num_tx_ring = TX_RING_SIZE;
        mdp->num_rx_ring = RX_RING_SIZE;
-       mdp->addr = ioremap(res->start, resource_size(res));
-       if (mdp->addr == NULL) {
-               ret = -ENOMEM;
-               dev_err(&pdev->dev, "ioremap failed.\n");
+       mdp->addr = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(mdp->addr)) {
+               ret = PTR_ERR(mdp->addr);
                goto out_release;
        }
 
@@ -2414,7 +2708,6 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        pm_runtime_resume(&pdev->dev);
 
-       pd = (struct sh_eth_plat_data *)(pdev->dev.platform_data);
        /* get PHY ID */
        mdp->phy_id = pd->phy;
        mdp->phy_interface = pd->phy_interface;
@@ -2452,15 +2745,13 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
                        ret = -ENODEV;
                        goto out_release;
                }
-               mdp->tsu_addr = ioremap(rtsu->start,
-                                       resource_size(rtsu));
-               if (mdp->tsu_addr == NULL) {
-                       ret = -ENOMEM;
-                       dev_err(&pdev->dev, "TSU ioremap failed.\n");
+               mdp->tsu_addr = devm_ioremap_resource(&pdev->dev, rtsu);
+               if (IS_ERR(mdp->tsu_addr)) {
+                       ret = PTR_ERR(mdp->tsu_addr);
                        goto out_release;
                }
                mdp->port = devno % 2;
-               ndev->features = NETIF_F_HW_VLAN_FILTER;
+               ndev->features = NETIF_F_HW_VLAN_CTAG_FILTER;
        }
 
        /* initialize first or needed device */
@@ -2497,10 +2788,6 @@ out_unregister:
 
 out_release:
        /* net_dev free */
-       if (mdp && mdp->addr)
-               iounmap(mdp->addr);
-       if (mdp && mdp->tsu_addr)
-               iounmap(mdp->tsu_addr);
        if (ndev)
                free_netdev(ndev);
 
@@ -2511,14 +2798,10 @@ out:
 static int sh_eth_drv_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
-       struct sh_eth_private *mdp = netdev_priv(ndev);
 
-       if (mdp->cd->tsu)
-               iounmap(mdp->tsu_addr);
        sh_mdio_release(ndev);
        unregister_netdev(ndev);
        pm_runtime_disable(&pdev->dev);
-       iounmap(mdp->addr);
        free_netdev(ndev);
        platform_set_drvdata(pdev, NULL);