net: sh_eth: Add r8a7794 support
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / net / ethernet / renesas / sh_eth.c
index d256ce1..177d263 100644 (file)
@@ -1,9 +1,9 @@
-/*
- *  SuperH Ethernet device driver
+/*  SuperH Ethernet device driver
  *
  *  Copyright (C) 2006-2012 Nobuhiro Iwamatsu
- *  Copyright (C) 2008-2013 Renesas Solutions Corp.
- *  Copyright (C) 2013 Cogent Embedded, Inc.
+ *  Copyright (C) 2008-2014 Renesas Solutions Corp.
+ *  Copyright (C) 2013-2014 Cogent Embedded, Inc.
+ *  Copyright (C) 2014 Codethink Limited
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms and conditions of the GNU General Public License,
  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  *  more details.
- *  You should have received a copy of the GNU General Public License along with
- *  this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  *
  *  The full GNU General Public License is included in this distribution in
  *  the file called "COPYING".
  */
 
-#include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/mdio-bitbang.h>
 #include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_net.h>
 #include <linux/phy.h>
 #include <linux/cache.h>
 #include <linux/io.h>
@@ -41,6 +41,7 @@
 #include <linux/if_vlan.h>
 #include <linux/clk.h>
 #include <linux/sh_eth.h>
+#include <linux/of_mdio.h>
 
 #include "sh_eth.h"
 
@@ -148,6 +149,65 @@ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
        [FWALCR1]       = 0x00b4,
 };
 
+static const u16 sh_eth_offset_fast_rz[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,
+       [RFLR]          = 0x0508,
+       [ECSR]          = 0x0510,
+       [ECSIPR]        = 0x0518,
+       [PIR]           = 0x0520,
+       [APR]           = 0x0554,
+       [MPR]           = 0x0558,
+       [PFTCR]         = 0x055c,
+       [PFRCR]         = 0x0560,
+       [TPAUSER]       = 0x0564,
+       [MAHR]          = 0x05c0,
+       [MALR]          = 0x05c8,
+       [CEFCR]         = 0x0740,
+       [FRECR]         = 0x0748,
+       [TSFRCR]        = 0x0750,
+       [TLFRCR]        = 0x0758,
+       [RFCR]          = 0x0760,
+       [MAFCR]         = 0x0778,
+
+       [ARSTR]         = 0x0000,
+       [TSU_CTRST]     = 0x0004,
+       [TSU_VTAG0]     = 0x0058,
+       [TSU_ADSBSY]    = 0x0060,
+       [TSU_TEN]       = 0x0064,
+       [TSU_ADRH0]     = 0x0100,
+       [TSU_ADRL0]     = 0x0104,
+       [TSU_ADRH31]    = 0x01f8,
+       [TSU_ADRL31]    = 0x01fc,
+
+       [TXNLCR0]       = 0x0080,
+       [TXALCR0]       = 0x0084,
+       [RXNLCR0]       = 0x0088,
+       [RXALCR0]       = 0x008C,
+};
+
 static const u16 sh_eth_offset_fast_rcar[SH_ETH_MAX_REGISTER_OFFSET] = {
        [ECMR]          = 0x0300,
        [RFLR]          = 0x0308,
@@ -247,6 +307,27 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
 };
 
 static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
+       [EDMR]          = 0x0000,
+       [EDTRR]         = 0x0004,
+       [EDRRR]         = 0x0008,
+       [TDLAR]         = 0x000c,
+       [RDLAR]         = 0x0010,
+       [EESR]          = 0x0014,
+       [EESIPR]        = 0x0018,
+       [TRSCER]        = 0x001c,
+       [RMFCR]         = 0x0020,
+       [TFTR]          = 0x0024,
+       [FDR]           = 0x0028,
+       [RMCR]          = 0x002c,
+       [EDOCR]         = 0x0030,
+       [FCFTR]         = 0x0034,
+       [RPADIR]        = 0x0038,
+       [TRIMD]         = 0x003c,
+       [RBWAR]         = 0x0040,
+       [RDFAR]         = 0x0044,
+       [TBRAR]         = 0x004c,
+       [TDFAR]         = 0x0050,
+
        [ECMR]          = 0x0160,
        [ECSR]          = 0x0164,
        [ECSIPR]        = 0x0168,
@@ -314,12 +395,14 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
        [TSU_ADRL31]    = 0x01fc,
 };
 
-static int sh_eth_is_gether(struct sh_eth_private *mdp)
+static bool sh_eth_is_gether(struct sh_eth_private *mdp)
 {
-       if (mdp->reg_offset == sh_eth_offset_gigabit)
-               return 1;
-       else
-               return 0;
+       return mdp->reg_offset == sh_eth_offset_gigabit;
+}
+
+static bool sh_eth_is_rz_fast_ether(struct sh_eth_private *mdp)
+{
+       return mdp->reg_offset == sh_eth_offset_fast_rz;
 }
 
 static void sh_eth_select_mii(struct net_device *ndev)
@@ -338,7 +421,8 @@ static void sh_eth_select_mii(struct net_device *ndev)
                value = 0x0;
                break;
        default:
-               pr_warn("PHY interface mode was not setup. Set to MII.\n");
+               netdev_warn(ndev,
+                           "PHY interface mode was not setup. Set to MII.\n");
                value = 0x1;
                break;
        }
@@ -395,8 +479,8 @@ static struct sh_eth_cpu_data r8a777x_data = {
        .hw_swap        = 1,
 };
 
-/* R8A7790 */
-static struct sh_eth_cpu_data r8a7790_data = {
+/* R8A7790/1 */
+static struct sh_eth_cpu_data r8a779x_data = {
        .set_duplex     = sh_eth_set_duplex,
        .set_rate       = sh_eth_set_rate_r8a777x,
 
@@ -483,7 +567,6 @@ static struct sh_eth_cpu_data sh7757_data = {
        .register_type  = SH_ETH_REG_FAST_SH4,
 
        .eesipr_value   = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
-       .rmcr_value     = RMCR_RNC,
 
        .tx_check       = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO,
        .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE |
@@ -561,7 +644,6 @@ static struct sh_eth_cpu_data sh7757_data_giga = {
                          EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
                          EESR_TDE | EESR_ECI,
        .fdr_value      = 0x0000072f,
-       .rmcr_value     = RMCR_RNC,
 
        .irq_flags      = IRQF_SHARED,
        .apr            = 1,
@@ -646,8 +728,8 @@ static struct sh_eth_cpu_data sh7763_data = {
        .eesipr_value   = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
 
        .tx_check       = EESR_TC1 | EESR_FTC,
-       .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
-                         EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
+       .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
+                         EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE |
                          EESR_ECI,
 
        .apr            = 1,
@@ -689,7 +771,6 @@ static struct sh_eth_cpu_data r8a7740_data = {
                          EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
                          EESR_TDE | EESR_ECI,
        .fdr_value      = 0x0000070f,
-       .rmcr_value     = RMCR_RNC,
 
        .apr            = 1,
        .mpr            = 1,
@@ -705,6 +786,37 @@ static struct sh_eth_cpu_data r8a7740_data = {
        .shift_rd0      = 1,
 };
 
+/* R7S72100 */
+static struct sh_eth_cpu_data r7s72100_data = {
+       .chip_reset     = sh_eth_chip_reset,
+       .set_duplex     = sh_eth_set_duplex,
+
+       .register_type  = SH_ETH_REG_FAST_RZ,
+
+       .ecsr_value     = ECSR_ICD,
+       .ecsipr_value   = ECSIPR_ICDIP,
+       .eesipr_value   = 0xff7f009f,
+
+       .tx_check       = EESR_TC1 | EESR_FTC,
+       .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
+                         EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE |
+                         EESR_TDE | EESR_ECI,
+       .fdr_value      = 0x0000070f,
+
+       .no_psr         = 1,
+       .apr            = 1,
+       .mpr            = 1,
+       .tpauser        = 1,
+       .hw_swap        = 1,
+       .rpadir         = 1,
+       .rpadir_value   = 2 << 16,
+       .no_trimd       = 1,
+       .no_ade         = 1,
+       .hw_crc         = 1,
+       .tsu            = 1,
+       .shift_rd0      = 1,
+};
+
 static struct sh_eth_cpu_data sh7619_data = {
        .register_type  = SH_ETH_REG_FAST_SH3_SH2,
 
@@ -732,15 +844,12 @@ static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd)
                cd->ecsipr_value = DEFAULT_ECSIPR_INIT;
 
        if (!cd->fcftr_value)
-               cd->fcftr_value = DEFAULT_FIFO_F_D_RFF | \
+               cd->fcftr_value = DEFAULT_FIFO_F_D_RFF |
                                  DEFAULT_FIFO_F_D_RFD;
 
        if (!cd->fdr_value)
                cd->fdr_value = DEFAULT_FDR_INIT;
 
-       if (!cd->rmcr_value)
-               cd->rmcr_value = DEFAULT_RMCR_VALUE;
-
        if (!cd->tx_check)
                cd->tx_check = DEFAULT_TX_CHECK;
 
@@ -760,7 +869,7 @@ static int sh_eth_check_reset(struct net_device *ndev)
                cnt--;
        }
        if (cnt <= 0) {
-               pr_err("Device reset failed\n");
+               netdev_err(ndev, "Device reset failed\n");
                ret = -ETIMEDOUT;
        }
        return ret;
@@ -771,14 +880,14 @@ static int sh_eth_reset(struct net_device *ndev)
        struct sh_eth_private *mdp = netdev_priv(ndev);
        int ret = 0;
 
-       if (sh_eth_is_gether(mdp)) {
+       if (sh_eth_is_gether(mdp) || sh_eth_is_rz_fast_ether(mdp)) {
                sh_eth_write(ndev, EDSR_ENALL, EDSR);
                sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER,
                             EDMR);
 
                ret = sh_eth_check_reset(ndev);
                if (ret)
-                       goto out;
+                       return ret;
 
                /* Table Init */
                sh_eth_write(ndev, 0x0, TDLAR);
@@ -805,7 +914,6 @@ static int sh_eth_reset(struct net_device *ndev)
                             EDMR);
        }
 
-out:
        return ret;
 }
 
@@ -849,20 +957,17 @@ static inline __u32 edmac_to_cpu(struct sh_eth_private *mdp, u32 x)
        return x;
 }
 
-/*
- * Program the hardware MAC address from dev->dev_addr.
- */
+/* Program the hardware MAC address from dev->dev_addr. */
 static void update_mac_address(struct net_device *ndev)
 {
        sh_eth_write(ndev,
-               (ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
-               (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), MAHR);
+                    (ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
+                    (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), MAHR);
        sh_eth_write(ndev,
-               (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), MALR);
+                    (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), MALR);
 }
 
-/*
- * Get MAC address from SuperH MAC address register
+/* Get MAC address from SuperH MAC address register
  *
  * SuperH's Ethernet device doesn't have 'ROM' to MAC address.
  * This driver get MAC address that use by bootloader(U-boot or sh-ipl+g).
@@ -885,7 +990,7 @@ static void read_mac_address(struct net_device *ndev, unsigned char *mac)
 
 static unsigned long sh_eth_get_edtrr_trns(struct sh_eth_private *mdp)
 {
-       if (sh_eth_is_gether(mdp))
+       if (sh_eth_is_gether(mdp) || sh_eth_is_rz_fast_ether(mdp))
                return EDTRR_TRNS_GETHER;
        else
                return EDTRR_TRNS_ETHER;
@@ -989,20 +1094,16 @@ static void sh_eth_ring_free(struct net_device *ndev)
 
        /* Free Rx skb ringbuffer */
        if (mdp->rx_skbuff) {
-               for (i = 0; i < mdp->num_rx_ring; i++) {
-                       if (mdp->rx_skbuff[i])
-                               dev_kfree_skb(mdp->rx_skbuff[i]);
-               }
+               for (i = 0; i < mdp->num_rx_ring; i++)
+                       dev_kfree_skb(mdp->rx_skbuff[i]);
        }
        kfree(mdp->rx_skbuff);
        mdp->rx_skbuff = NULL;
 
        /* Free Tx skb ringbuffer */
        if (mdp->tx_skbuff) {
-               for (i = 0; i < mdp->num_tx_ring; i++) {
-                       if (mdp->tx_skbuff[i])
-                               dev_kfree_skb(mdp->tx_skbuff[i]);
-               }
+               for (i = 0; i < mdp->num_tx_ring; i++)
+                       dev_kfree_skb(mdp->tx_skbuff[i]);
        }
        kfree(mdp->tx_skbuff);
        mdp->tx_skbuff = NULL;
@@ -1019,8 +1120,10 @@ static void sh_eth_ring_format(struct net_device *ndev)
        int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring;
        int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring;
 
-       mdp->cur_rx = mdp->cur_tx = 0;
-       mdp->dirty_rx = mdp->dirty_tx = 0;
+       mdp->cur_rx = 0;
+       mdp->cur_tx = 0;
+       mdp->dirty_rx = 0;
+       mdp->dirty_tx = 0;
 
        memset(mdp->rx_ring, 0, rx_ringsize);
 
@@ -1033,7 +1136,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
                if (skb == NULL)
                        break;
                dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
-                               DMA_FROM_DEVICE);
+                              DMA_FROM_DEVICE);
                sh_eth_set_receive_align(skb);
 
                /* RX descriptor */
@@ -1046,7 +1149,8 @@ static void sh_eth_ring_format(struct net_device *ndev)
                /* Rx descriptor address set */
                if (i == 0) {
                        sh_eth_write(ndev, mdp->rx_desc_dma, RDLAR);
-                       if (sh_eth_is_gether(mdp))
+                       if (sh_eth_is_gether(mdp) ||
+                           sh_eth_is_rz_fast_ether(mdp))
                                sh_eth_write(ndev, mdp->rx_desc_dma, RDFAR);
                }
        }
@@ -1067,7 +1171,8 @@ static void sh_eth_ring_format(struct net_device *ndev)
                if (i == 0) {
                        /* Tx descriptor address set */
                        sh_eth_write(ndev, mdp->tx_desc_dma, TDLAR);
-                       if (sh_eth_is_gether(mdp))
+                       if (sh_eth_is_gether(mdp) ||
+                           sh_eth_is_rz_fast_ether(mdp))
                                sh_eth_write(ndev, mdp->tx_desc_dma, TDFAR);
                }
        }
@@ -1081,8 +1186,7 @@ static int sh_eth_ring_init(struct net_device *ndev)
        struct sh_eth_private *mdp = netdev_priv(ndev);
        int rx_ringsize, tx_ringsize, ret = 0;
 
-       /*
-        * +26 gets the maximum ethernet encapsulation, +7 & ~7 because the
+       /* +26 gets the maximum ethernet encapsulation, +7 & ~7 because the
         * card needs room to do 8 byte alignment, +2 so we can reserve
         * the first 2 bytes, and +16 gets room for the status word from the
         * card.
@@ -1169,7 +1273,7 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start)
        /* Soft Reset */
        ret = sh_eth_reset(ndev);
        if (ret)
-               goto out;
+               return ret;
 
        if (mdp->cd->rmiimode)
                sh_eth_write(ndev, 0x1, RMIIMODE);
@@ -1193,8 +1297,8 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start)
        sh_eth_write(ndev, mdp->cd->fdr_value, FDR);
        sh_eth_write(ndev, 0, TFTR);
 
-       /* Frame recv control */
-       sh_eth_write(ndev, mdp->cd->rmcr_value, RMCR);
+       /* Frame recv control (enable multiple-packets per rx irq) */
+       sh_eth_write(ndev, RMCR_RNC, RMCR);
 
        sh_eth_write(ndev, DESC_I_RINT8 | DESC_I_RINT5 | DESC_I_TINT2, TRSCER);
 
@@ -1248,7 +1352,6 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start)
                netif_start_queue(ndev);
        }
 
-out:
        return ret;
 }
 
@@ -1257,7 +1360,7 @@ static int sh_eth_txfree(struct net_device *ndev)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        struct sh_eth_txdesc *txdesc;
-       int freeNum = 0;
+       int free_num = 0;
        int entry = 0;
 
        for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
@@ -1271,7 +1374,7 @@ static int sh_eth_txfree(struct net_device *ndev)
                                         txdesc->buffer_length, DMA_TO_DEVICE);
                        dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
                        mdp->tx_skbuff[entry] = NULL;
-                       freeNum++;
+                       free_num++;
                }
                txdesc->status = cpu_to_edmac(mdp, TD_TFP);
                if (entry >= mdp->num_tx_ring - 1)
@@ -1280,7 +1383,7 @@ static int sh_eth_txfree(struct net_device *ndev)
                ndev->stats.tx_packets++;
                ndev->stats.tx_bytes += txdesc->buffer_length;
        }
-       return freeNum;
+       return free_num;
 }
 
 /* Packet receive function */
@@ -1292,7 +1395,6 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
        int entry = mdp->cur_rx % mdp->num_rx_ring;
        int boguscnt = (mdp->dirty_rx + mdp->num_rx_ring) - mdp->cur_rx;
        struct sk_buff *skb;
-       int exceeded = 0;
        u16 pkt_len = 0;
        u32 desc_status;
 
@@ -1304,21 +1406,19 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                if (--boguscnt < 0)
                        break;
 
-               if (*quota <= 0) {
-                       exceeded = 1;
+               if (*quota <= 0)
                        break;
-               }
+
                (*quota)--;
 
                if (!(desc_status & RDFEND))
                        ndev->stats.rx_length_errors++;
 
-               /*
-                * In case of almost all GETHER/ETHERs, the Receive Frame State
+               /* In case of almost all GETHER/ETHERs, the Receive Frame State
                 * (RFS) bits in the Receive Descriptor 0 are from bit 9 to
-                * bit 0. However, in case of the R8A7740's GETHER, the RFS
-                * bits are from bit 25 to bit 16. So, the driver needs right
-                * shifting by 16.
+                * bit 0. However, in case of the R8A7740, R8A779x, and
+                * R7S72100 the RFS bits are from bit 25 to bit 16. So, the
+                * driver needs right shifting by 16.
                 */
                if (mdp->cd->shift_rd0)
                        desc_status >>= 16;
@@ -1356,7 +1456,6 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                        ndev->stats.rx_packets++;
                        ndev->stats.rx_bytes += pkt_len;
                }
-               rxdesc->status |= cpu_to_edmac(mdp, RD_RACT);
                entry = (++mdp->cur_rx) % mdp->num_rx_ring;
                rxdesc = &mdp->rx_ring[entry];
        }
@@ -1374,7 +1473,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                        if (skb == NULL)
                                break;  /* Better luck next round. */
                        dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
-                                       DMA_FROM_DEVICE);
+                                      DMA_FROM_DEVICE);
                        sh_eth_set_receive_align(skb);
 
                        skb_checksum_none_assert(skb);
@@ -1392,14 +1491,17 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
        /* If we don't need to check status, don't. -KDU */
        if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) {
                /* fix the values for the next receiving if RDE is set */
-               if (intr_status & EESR_RDE)
-                       mdp->cur_rx = mdp->dirty_rx =
-                               (sh_eth_read(ndev, RDFAR) -
-                                sh_eth_read(ndev, RDLAR)) >> 4;
+               if (intr_status & EESR_RDE) {
+                       u32 count = (sh_eth_read(ndev, RDFAR) -
+                                    sh_eth_read(ndev, RDLAR)) >> 4;
+
+                       mdp->cur_rx = count;
+                       mdp->dirty_rx = count;
+               }
                sh_eth_write(ndev, EDRRR_R, EDRRR);
        }
 
-       return exceeded;
+       return *quota <= 0;
 }
 
 static void sh_eth_rcv_snd_disable(struct net_device *ndev)
@@ -1438,17 +1540,17 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
                                if (mdp->ether_link_active_low)
                                        link_stat = ~link_stat;
                        }
-                       if (!(link_stat & PHY_ST_LINK))
+                       if (!(link_stat & PHY_ST_LINK)) {
                                sh_eth_rcv_snd_disable(ndev);
-                       else {
+                       else {
                                /* Link Up */
                                sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) &
-                                         ~DMAC_M_ECI, EESIPR);
-                               /*clear int */
+                                                  ~DMAC_M_ECI, EESIPR);
+                               /* clear int */
                                sh_eth_write(ndev, sh_eth_read(ndev, ECSR),
-                                         ECSR);
+                                            ECSR);
                                sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) |
-                                         DMAC_M_ECI, EESIPR);
+                                                  DMAC_M_ECI, EESIPR);
                                /* enable tx and rx */
                                sh_eth_rcv_snd_enable(ndev);
                        }
@@ -1460,8 +1562,7 @@ ignore_link:
                /* Unused write back interrupt */
                if (intr_status & EESR_TABT) {  /* Transmit Abort int */
                        ndev->stats.tx_aborted_errors++;
-                       if (netif_msg_tx_err(mdp))
-                               dev_err(&ndev->dev, "Transmit Abort\n");
+                       netif_err(mdp, tx_err, ndev, "Transmit Abort\n");
                }
        }
 
@@ -1470,45 +1571,38 @@ ignore_link:
                if (intr_status & EESR_RFRMER) {
                        /* Receive Frame Overflow int */
                        ndev->stats.rx_frame_errors++;
-                       if (netif_msg_rx_err(mdp))
-                               dev_err(&ndev->dev, "Receive Abort\n");
+                       netif_err(mdp, rx_err, ndev, "Receive Abort\n");
                }
        }
 
        if (intr_status & EESR_TDE) {
                /* Transmit Descriptor Empty int */
                ndev->stats.tx_fifo_errors++;
-               if (netif_msg_tx_err(mdp))
-                       dev_err(&ndev->dev, "Transmit Descriptor Empty\n");
+               netif_err(mdp, tx_err, ndev, "Transmit Descriptor Empty\n");
        }
 
        if (intr_status & EESR_TFE) {
                /* FIFO under flow */
                ndev->stats.tx_fifo_errors++;
-               if (netif_msg_tx_err(mdp))
-                       dev_err(&ndev->dev, "Transmit FIFO Under flow\n");
+               netif_err(mdp, tx_err, ndev, "Transmit FIFO Under flow\n");
        }
 
        if (intr_status & EESR_RDE) {
                /* Receive Descriptor Empty int */
                ndev->stats.rx_over_errors++;
-
-               if (netif_msg_rx_err(mdp))
-                       dev_err(&ndev->dev, "Receive Descriptor Empty\n");
+               netif_err(mdp, rx_err, ndev, "Receive Descriptor Empty\n");
        }
 
        if (intr_status & EESR_RFE) {
                /* Receive FIFO Overflow int */
                ndev->stats.rx_fifo_errors++;
-               if (netif_msg_rx_err(mdp))
-                       dev_err(&ndev->dev, "Receive FIFO Overflow\n");
+               netif_err(mdp, rx_err, ndev, "Receive FIFO Overflow\n");
        }
 
        if (!mdp->cd->no_ade && (intr_status & EESR_ADE)) {
                /* Address Error */
                ndev->stats.tx_fifo_errors++;
-               if (netif_msg_tx_err(mdp))
-                       dev_err(&ndev->dev, "Address Error\n");
+               netif_err(mdp, tx_err, ndev, "Address Error\n");
        }
 
        mask = EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE;
@@ -1517,11 +1611,11 @@ ignore_link:
        if (intr_status & mask) {
                /* Tx error */
                u32 edtrr = sh_eth_read(ndev, EDTRR);
+
                /* dmesg */
-               dev_err(&ndev->dev, "TX error. status=%8.8x cur_tx=%8.8x ",
-                               intr_status, mdp->cur_tx);
-               dev_err(&ndev->dev, "dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n",
-                               mdp->dirty_tx, (u32) ndev->state, edtrr);
+               netdev_err(ndev, "TX error. status=%8.8x cur_tx=%8.8x dirty_tx=%8.8x state=%8.8x EDTRR=%8.8x.\n",
+                          intr_status, mdp->cur_tx, mdp->dirty_tx,
+                          (u32)ndev->state, edtrr);
                /* dirty buffer free */
                sh_eth_txfree(ndev);
 
@@ -1566,9 +1660,9 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
                                     EESIPR);
                        __napi_schedule(&mdp->napi);
                } else {
-                       dev_warn(&ndev->dev,
-                                "ignoring interrupt, status 0x%08lx, mask 0x%08lx.\n",
-                                intr_status, intr_enable);
+                       netdev_warn(ndev,
+                                   "ignoring interrupt, status 0x%08lx, mask 0x%08lx.\n",
+                                   intr_status, intr_enable);
                }
        }
 
@@ -1644,7 +1738,8 @@ static void sh_eth_adjust_link(struct net_device *ndev)
                }
                if (!mdp->link) {
                        sh_eth_write(ndev,
-                               (sh_eth_read(ndev, ECMR) & ~ECMR_TXF), ECMR);
+                                    sh_eth_read(ndev, ECMR) & ~ECMR_TXF,
+                                    ECMR);
                        new_state = 1;
                        mdp->link = phydev->link;
                        if (mdp->cd->no_psr || mdp->no_ether_link)
@@ -1666,27 +1761,42 @@ static void sh_eth_adjust_link(struct net_device *ndev)
 /* PHY init function */
 static int sh_eth_phy_init(struct net_device *ndev)
 {
+       struct device_node *np = ndev->dev.parent->of_node;
        struct sh_eth_private *mdp = netdev_priv(ndev);
-       char phy_id[MII_BUS_ID_SIZE + 3];
        struct phy_device *phydev = NULL;
 
-       snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
-               mdp->mii_bus->id , mdp->phy_id);
-
        mdp->link = 0;
        mdp->speed = 0;
        mdp->duplex = -1;
 
        /* Try connect to PHY */
-       phydev = phy_connect(ndev, phy_id, sh_eth_adjust_link,
-                            mdp->phy_interface);
+       if (np) {
+               struct device_node *pn;
+
+               pn = of_parse_phandle(np, "phy-handle", 0);
+               phydev = of_phy_connect(ndev, pn,
+                                       sh_eth_adjust_link, 0,
+                                       mdp->phy_interface);
+
+               if (!phydev)
+                       phydev = ERR_PTR(-ENOENT);
+       } else {
+               char phy_id[MII_BUS_ID_SIZE + 3];
+
+               snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
+                        mdp->mii_bus->id, mdp->phy_id);
+
+               phydev = phy_connect(ndev, phy_id, sh_eth_adjust_link,
+                                    mdp->phy_interface);
+       }
+
        if (IS_ERR(phydev)) {
-               dev_err(&ndev->dev, "phy_connect failed\n");
+               netdev_err(ndev, "failed to connect PHY\n");
                return PTR_ERR(phydev);
        }
 
-       dev_info(&ndev->dev, "attached phy %i to driver %s\n",
-               phydev->addr, phydev->drv->name);
+       netdev_info(ndev, "attached PHY %d (IRQ %d) to driver %s\n",
+                   phydev->addr, phydev->irq, phydev->drv->name);
 
        mdp->phydev = phydev;
 
@@ -1703,15 +1813,13 @@ static int sh_eth_phy_start(struct net_device *ndev)
        if (ret)
                return ret;
 
-       /* reset phy - this also wakes it from PDOWN */
-       phy_write(mdp->phydev, MII_BMCR, BMCR_RESET);
        phy_start(mdp->phydev);
 
        return 0;
 }
 
 static int sh_eth_get_settings(struct net_device *ndev,
-                       struct ethtool_cmd *ecmd)
+                              struct ethtool_cmd *ecmd)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        unsigned long flags;
@@ -1725,7 +1833,7 @@ static int sh_eth_get_settings(struct net_device *ndev,
 }
 
 static int sh_eth_set_settings(struct net_device *ndev,
-               struct ethtool_cmd *ecmd)
+                              struct ethtool_cmd *ecmd)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        unsigned long flags;
@@ -1801,7 +1909,7 @@ static int sh_eth_get_sset_count(struct net_device *netdev, int sset)
 }
 
 static void sh_eth_get_ethtool_stats(struct net_device *ndev,
-                       struct ethtool_stats *stats, u64 *data)
+                                    struct ethtool_stats *stats, u64 *data)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        int i = 0;
@@ -1818,7 +1926,7 @@ static void sh_eth_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
        switch (stringset) {
        case ETH_SS_STATS:
                memcpy(data, *sh_eth_gstrings_stats,
-                                       sizeof(sh_eth_gstrings_stats));
+                      sizeof(sh_eth_gstrings_stats));
                break;
        }
 }
@@ -1869,12 +1977,12 @@ static int sh_eth_set_ringparam(struct net_device *ndev,
 
        ret = sh_eth_ring_init(ndev);
        if (ret < 0) {
-               dev_err(&ndev->dev, "%s: sh_eth_ring_init failed.\n", __func__);
+               netdev_err(ndev, "%s: sh_eth_ring_init failed.\n", __func__);
                return ret;
        }
        ret = sh_eth_dev_init(ndev, false);
        if (ret < 0) {
-               dev_err(&ndev->dev, "%s: sh_eth_dev_init failed.\n", __func__);
+               netdev_err(ndev, "%s: sh_eth_dev_init failed.\n", __func__);
                return ret;
        }
 
@@ -1915,7 +2023,7 @@ static int sh_eth_open(struct net_device *ndev)
        ret = request_irq(ndev->irq, sh_eth_interrupt,
                          mdp->cd->irq_flags, ndev->name, ndev);
        if (ret) {
-               dev_err(&ndev->dev, "Can not assign IRQ number\n");
+               netdev_err(ndev, "Can not assign IRQ number\n");
                goto out_napi_off;
        }
 
@@ -1953,9 +2061,9 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
 
        netif_stop_queue(ndev);
 
-       if (netif_msg_timer(mdp))
-               dev_err(&ndev->dev, "%s: transmit timed out, status %8.8x,"
-              " resetting...\n", ndev->name, (int)sh_eth_read(ndev, EESR));
+       netif_err(mdp, timer, ndev,
+                 "transmit timed out, status %8.8x, resetting...\n",
+                 (int)sh_eth_read(ndev, EESR));
 
        /* tx_errors count up */
        ndev->stats.tx_errors++;
@@ -1965,13 +2073,11 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
                rxdesc = &mdp->rx_ring[i];
                rxdesc->status = 0;
                rxdesc->addr = 0xBADF00D0;
-               if (mdp->rx_skbuff[i])
-                       dev_kfree_skb(mdp->rx_skbuff[i]);
+               dev_kfree_skb(mdp->rx_skbuff[i]);
                mdp->rx_skbuff[i] = NULL;
        }
        for (i = 0; i < mdp->num_tx_ring; i++) {
-               if (mdp->tx_skbuff[i])
-                       dev_kfree_skb(mdp->tx_skbuff[i]);
+               dev_kfree_skb(mdp->tx_skbuff[i]);
                mdp->tx_skbuff[i] = NULL;
        }
 
@@ -1990,8 +2096,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        spin_lock_irqsave(&mdp->lock, flags);
        if ((mdp->cur_tx - mdp->dirty_tx) >= (mdp->num_tx_ring - 4)) {
                if (!sh_eth_txfree(ndev)) {
-                       if (netif_msg_tx_queued(mdp))
-                               dev_warn(&ndev->dev, "TxFD exhausted.\n");
+                       netif_warn(mdp, tx_queued, ndev, "TxFD exhausted.\n");
                        netif_stop_queue(ndev);
                        spin_unlock_irqrestore(&mdp->lock, flags);
                        return NETDEV_TX_BUSY;
@@ -2008,8 +2113,8 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                                 skb->len + 2);
        txdesc->addr = dma_map_single(&ndev->dev, skb->data, skb->len,
                                      DMA_TO_DEVICE);
-       if (skb->len < ETHERSMALL)
-               txdesc->buffer_length = ETHERSMALL;
+       if (skb->len < ETH_ZLEN)
+               txdesc->buffer_length = ETH_ZLEN;
        else
                txdesc->buffer_length = skb->len;
 
@@ -2065,6 +2170,9 @@ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
 
+       if (sh_eth_is_rz_fast_ether(mdp))
+               return &ndev->stats;
+
        pm_runtime_get_sync(&mdp->pdev->dev);
 
        ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR);
@@ -2088,8 +2196,7 @@ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
 }
 
 /* ioctl to device function */
-static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq,
-                               int cmd)
+static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        struct phy_device *phydev = mdp->phydev;
@@ -2159,7 +2266,7 @@ static int sh_eth_tsu_busy(struct net_device *ndev)
                udelay(10);
                timeout--;
                if (timeout <= 0) {
-                       dev_err(&ndev->dev, "%s: timeout\n", __func__);
+                       netdev_err(ndev, "%s: timeout\n", __func__);
                        return -ETIMEDOUT;
                }
        }
@@ -2209,7 +2316,7 @@ static int sh_eth_tsu_find_entry(struct net_device *ndev, const u8 *addr)
 
        for (i = 0; i < SH_ETH_TSU_CAM_ENTRIES; i++, reg_offset += 8) {
                sh_eth_tsu_read_entry(reg_offset, c_addr);
-               if (memcmp(addr, c_addr, ETH_ALEN) == 0)
+               if (ether_addr_equal(addr, c_addr))
                        return i;
        }
 
@@ -2344,8 +2451,7 @@ static void sh_eth_set_multicast_list(struct net_device *ndev)
        unsigned long flags;
 
        spin_lock_irqsave(&mdp->lock, flags);
-       /*
-        * Initial condition is MCT = 1, PRM = 0.
+       /* Initial condition is MCT = 1, PRM = 0.
         * Depending on ndev->flags, set PRM or clear MCT
         */
        ecmr_bits = (sh_eth_read(ndev, ECMR) & ~ECMR_PRM) | ECMR_MCT;
@@ -2411,8 +2517,7 @@ static int sh_eth_vlan_rx_add_vid(struct net_device *ndev,
 
        mdp->vlan_num_ids++;
 
-       /*
-        * The controller has one VLAN tag HW filter. So, if the filter is
+       /* The controller has one VLAN tag HW filter. So, if the filter is
         * already enabled, the driver disables it and the filte
         */
        if (mdp->vlan_num_ids > 1) {
@@ -2449,6 +2554,11 @@ static int sh_eth_vlan_rx_kill_vid(struct net_device *ndev,
 /* SuperH's TSU register init function */
 static void sh_eth_tsu_init(struct sh_eth_private *mdp)
 {
+       if (sh_eth_is_rz_fast_ether(mdp)) {
+               sh_eth_tsu_write(mdp, 0, TSU_TEN); /* Disable all CAM entry */
+               return;
+       }
+
        sh_eth_tsu_write(mdp, 0, TSU_FWEN0);    /* Disable forward(0->1) */
        sh_eth_tsu_write(mdp, 0, TSU_FWEN1);    /* Disable forward(1->0) */
        sh_eth_tsu_write(mdp, 0, TSU_FCM);      /* forward fifo 3k-3k */
@@ -2476,37 +2586,30 @@ static void sh_eth_tsu_init(struct sh_eth_private *mdp)
 }
 
 /* MDIO bus release function */
-static int sh_mdio_release(struct net_device *ndev)
+static int sh_mdio_release(struct sh_eth_private *mdp)
 {
-       struct mii_bus *bus = dev_get_drvdata(&ndev->dev);
-
        /* unregister mdio bus */
-       mdiobus_unregister(bus);
-
-       /* remove mdio bus info from net_device */
-       dev_set_drvdata(&ndev->dev, NULL);
+       mdiobus_unregister(mdp->mii_bus);
 
        /* free bitbang info */
-       free_mdio_bitbang(bus);
+       free_mdio_bitbang(mdp->mii_bus);
 
        return 0;
 }
 
 /* MDIO bus init function */
-static int sh_mdio_init(struct net_device *ndev, int id,
+static int sh_mdio_init(struct sh_eth_private *mdp,
                        struct sh_eth_plat_data *pd)
 {
        int ret, i;
        struct bb_info *bitbang;
-       struct sh_eth_private *mdp = netdev_priv(ndev);
+       struct platform_device *pdev = mdp->pdev;
+       struct device *dev = &mdp->pdev->dev;
 
        /* create bit control struct for PHY */
-       bitbang = devm_kzalloc(&ndev->dev, sizeof(struct bb_info),
-                              GFP_KERNEL);
-       if (!bitbang) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       bitbang = devm_kzalloc(dev, sizeof(struct bb_info), GFP_KERNEL);
+       if (!bitbang)
+               return -ENOMEM;
 
        /* bitbang init */
        bitbang->addr = mdp->addr + mdp->reg_offset[PIR];
@@ -2519,42 +2622,42 @@ static int sh_mdio_init(struct net_device *ndev, int id,
 
        /* MII controller setting */
        mdp->mii_bus = alloc_mdio_bitbang(&bitbang->ctrl);
-       if (!mdp->mii_bus) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!mdp->mii_bus)
+               return -ENOMEM;
 
        /* Hook up MII support for ethtool */
        mdp->mii_bus->name = "sh_mii";
-       mdp->mii_bus->parent = &ndev->dev;
+       mdp->mii_bus->parent = dev;
        snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
-               mdp->pdev->name, id);
+                pdev->name, pdev->id);
 
        /* PHY IRQ */
-       mdp->mii_bus->irq = devm_kzalloc(&ndev->dev,
-                                        sizeof(int) * PHY_MAX_ADDR,
-                                        GFP_KERNEL);
+       mdp->mii_bus->irq = devm_kmalloc_array(dev, PHY_MAX_ADDR, sizeof(int),
+                                              GFP_KERNEL);
        if (!mdp->mii_bus->irq) {
                ret = -ENOMEM;
                goto out_free_bus;
        }
 
-       for (i = 0; i < PHY_MAX_ADDR; i++)
-               mdp->mii_bus->irq[i] = PHY_POLL;
+       /* register MDIO bus */
+       if (dev->of_node) {
+               ret = of_mdiobus_register(mdp->mii_bus, dev->of_node);
+       } else {
+               for (i = 0; i < PHY_MAX_ADDR; i++)
+                       mdp->mii_bus->irq[i] = PHY_POLL;
+               if (pd->phy_irq > 0)
+                       mdp->mii_bus->irq[pd->phy] = pd->phy_irq;
+
+               ret = mdiobus_register(mdp->mii_bus);
+       }
 
-       /* register mdio bus */
-       ret = mdiobus_register(mdp->mii_bus);
        if (ret)
                goto out_free_bus;
 
-       dev_set_drvdata(&ndev->dev, mdp->mii_bus);
-
        return 0;
 
 out_free_bus:
        free_mdio_bitbang(mdp->mii_bus);
-
-out:
        return ret;
 }
 
@@ -2566,6 +2669,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_RZ:
+               reg_offset = sh_eth_offset_fast_rz;
+               break;
        case SH_ETH_REG_FAST_RCAR:
                reg_offset = sh_eth_offset_fast_rcar;
                break;
@@ -2576,7 +2682,6 @@ static const u16 *sh_eth_get_register_offset(int register_type)
                reg_offset = sh_eth_offset_fast_sh3_sh2;
                break;
        default:
-               pr_err("Unknown register type (%d)\n", register_type);
                break;
        }
 
@@ -2610,6 +2715,49 @@ static const struct net_device_ops sh_eth_netdev_ops_tsu = {
        .ndo_change_mtu         = eth_change_mtu,
 };
 
+#ifdef CONFIG_OF
+static struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev)
+{
+       struct device_node *np = dev->of_node;
+       struct sh_eth_plat_data *pdata;
+       const char *mac_addr;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL;
+
+       pdata->phy_interface = of_get_phy_mode(np);
+
+       mac_addr = of_get_mac_address(np);
+       if (mac_addr)
+               memcpy(pdata->mac_addr, mac_addr, ETH_ALEN);
+
+       pdata->no_ether_link =
+               of_property_read_bool(np, "renesas,no-ether-link");
+       pdata->ether_link_active_low =
+               of_property_read_bool(np, "renesas,ether-link-active-low");
+
+       return pdata;
+}
+
+static const struct of_device_id sh_eth_match_table[] = {
+       { .compatible = "renesas,gether-r8a7740", .data = &r8a7740_data },
+       { .compatible = "renesas,ether-r8a7778", .data = &r8a777x_data },
+       { .compatible = "renesas,ether-r8a7779", .data = &r8a777x_data },
+       { .compatible = "renesas,ether-r8a7790", .data = &r8a779x_data },
+       { .compatible = "renesas,ether-r8a7791", .data = &r8a779x_data },
+       { .compatible = "renesas,ether-r8a7794", .data = &r8a779x_data },
+       { .compatible = "renesas,ether-r7s72100", .data = &r7s72100_data },
+       { }
+};
+MODULE_DEVICE_TABLE(of, sh_eth_match_table);
+#else
+static inline struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev)
+{
+       return NULL;
+}
+#endif
+
 static int sh_eth_drv_probe(struct platform_device *pdev)
 {
        int ret, devno = 0;
@@ -2623,15 +2771,15 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (unlikely(res == NULL)) {
                dev_err(&pdev->dev, "invalid resource\n");
-               ret = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
        ndev = alloc_etherdev(sizeof(struct sh_eth_private));
-       if (!ndev) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!ndev)
+               return -ENOMEM;
+
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
 
        /* The sh Ether-specific entries in the device structure. */
        ndev->base_addr = res->start;
@@ -2660,9 +2808,9 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 
        spin_lock_init(&mdp->lock);
        mdp->pdev = pdev;
-       pm_runtime_enable(&pdev->dev);
-       pm_runtime_resume(&pdev->dev);
 
+       if (pdev->dev.of_node)
+               pd = sh_eth_parse_dt(&pdev->dev);
        if (!pd) {
                dev_err(&pdev->dev, "no platform data\n");
                ret = -EINVAL;
@@ -2678,8 +2826,22 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
        mdp->ether_link_active_low = pd->ether_link_active_low;
 
        /* set cpu data */
-       mdp->cd = (struct sh_eth_cpu_data *)id->driver_data;
+       if (id) {
+               mdp->cd = (struct sh_eth_cpu_data *)id->driver_data;
+       } else  {
+               const struct of_device_id *match;
+
+               match = of_match_device(of_match_ptr(sh_eth_match_table),
+                                       &pdev->dev);
+               mdp->cd = (struct sh_eth_cpu_data *)match->data;
+       }
        mdp->reg_offset = sh_eth_get_register_offset(mdp->cd->register_type);
+       if (!mdp->reg_offset) {
+               dev_err(&pdev->dev, "Unknown register type (%d)\n",
+                       mdp->cd->register_type);
+               ret = -EINVAL;
+               goto out_release;
+       }
        sh_eth_set_default_cpu_data(mdp->cd);
 
        /* set function */
@@ -2725,6 +2887,13 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
                }
        }
 
+       /* MDIO bus init */
+       ret = sh_mdio_init(mdp, pd);
+       if (ret) {
+               dev_err(&ndev->dev, "failed to initialise MDIO\n");
+               goto out_release;
+       }
+
        netif_napi_add(ndev, &mdp->napi, sh_eth_poll, 64);
 
        /* network device register */
@@ -2732,31 +2901,26 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
        if (ret)
                goto out_napi_del;
 
-       /* mdio bus init */
-       ret = sh_mdio_init(ndev, pdev->id, pd);
-       if (ret)
-               goto out_unregister;
-
        /* print device information */
-       pr_info("Base address at 0x%x, %pM, IRQ %d.\n",
-              (u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
+       netdev_info(ndev, "Base address at 0x%x, %pM, IRQ %d.\n",
+                   (u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
 
+       pm_runtime_put(&pdev->dev);
        platform_set_drvdata(pdev, ndev);
 
        return ret;
 
-out_unregister:
-       unregister_netdev(ndev);
-
 out_napi_del:
        netif_napi_del(&mdp->napi);
+       sh_mdio_release(mdp);
 
 out_release:
        /* net_dev free */
        if (ndev)
                free_netdev(ndev);
 
-out:
+       pm_runtime_put(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
        return ret;
 }
 
@@ -2765,9 +2929,9 @@ 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);
 
-       sh_mdio_release(ndev);
        unregister_netdev(ndev);
        netif_napi_del(&mdp->napi);
+       sh_mdio_release(mdp);
        pm_runtime_disable(&pdev->dev);
        free_netdev(ndev);
 
@@ -2777,8 +2941,7 @@ static int sh_eth_drv_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int sh_eth_runtime_nop(struct device *dev)
 {
-       /*
-        * Runtime PM callback shared between ->runtime_suspend()
+       /* Runtime PM callback shared between ->runtime_suspend()
         * and ->runtime_resume(). Simply returns success.
         *
         * This driver re-initializes all registers after
@@ -2805,9 +2968,12 @@ static struct platform_device_id sh_eth_id_table[] = {
        { "sh7757-ether", (kernel_ulong_t)&sh7757_data },
        { "sh7757-gether", (kernel_ulong_t)&sh7757_data_giga },
        { "sh7763-gether", (kernel_ulong_t)&sh7763_data },
+       { "r7s72100-ether", (kernel_ulong_t)&r7s72100_data },
        { "r8a7740-gether", (kernel_ulong_t)&r8a7740_data },
        { "r8a777x-ether", (kernel_ulong_t)&r8a777x_data },
-       { "r8a7790-ether", (kernel_ulong_t)&r8a7790_data },
+       { "r8a7790-ether", (kernel_ulong_t)&r8a779x_data },
+       { "r8a7791-ether", (kernel_ulong_t)&r8a779x_data },
+       { "r8a7794-ether", (kernel_ulong_t)&r8a779x_data },
        { }
 };
 MODULE_DEVICE_TABLE(platform, sh_eth_id_table);
@@ -2819,6 +2985,7 @@ static struct platform_driver sh_eth_driver = {
        .driver = {
                   .name = CARDNAME,
                   .pm = SH_ETH_PM_OPS,
+                  .of_match_table = of_match_ptr(sh_eth_match_table),
        },
 };