sh_eth: use EDMR_SRST_GETHER in sh_eth_check_reset()
[cascardo/linux.git] / drivers / net / ethernet / renesas / sh_eth.c
index 7384499..3d7a40a 100644 (file)
@@ -3,7 +3,7 @@
  *  Copyright (C) 2014  Renesas Electronics Corporation
  *  Copyright (C) 2006-2012 Nobuhiro Iwamatsu
  *  Copyright (C) 2008-2014 Renesas Solutions Corp.
- *  Copyright (C) 2013-2014 Cogent Embedded, Inc.
+ *  Copyright (C) 2013-2016 Cogent Embedded, Inc.
  *  Copyright (C) 2014 Codethink Limited
  *
  *  This program is free software; you can redistribute it and/or modify it
@@ -428,6 +428,13 @@ static u32 sh_eth_read(struct net_device *ndev, int enum_index)
        return ioread32(mdp->addr + offset);
 }
 
+static void sh_eth_modify(struct net_device *ndev, int enum_index, u32 clear,
+                         u32 set)
+{
+       sh_eth_write(ndev, (sh_eth_read(ndev, enum_index) & ~clear) | set,
+                    enum_index);
+}
+
 static bool sh_eth_is_gether(struct sh_eth_private *mdp)
 {
        return mdp->reg_offset == sh_eth_offset_gigabit;
@@ -440,8 +447,8 @@ static bool sh_eth_is_rz_fast_ether(struct sh_eth_private *mdp)
 
 static void sh_eth_select_mii(struct net_device *ndev)
 {
-       u32 value = 0x0;
        struct sh_eth_private *mdp = netdev_priv(ndev);
+       u32 value;
 
        switch (mdp->phy_interface) {
        case PHY_INTERFACE_MODE_GMII:
@@ -467,10 +474,7 @@ 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);
+       sh_eth_modify(ndev, ECMR, ECMR_DM, mdp->duplex ? ECMR_DM : 0);
 }
 
 static void sh_eth_chip_reset(struct net_device *ndev)
@@ -496,8 +500,6 @@ static void sh_eth_set_rate_gether(struct net_device *ndev)
        case 1000: /* 1000BASE */
                sh_eth_write(ndev, GECMR_1000, GECMR);
                break;
-       default:
-               break;
        }
 }
 
@@ -583,12 +585,10 @@ static void sh_eth_set_rate_r8a777x(struct net_device *ndev)
 
        switch (mdp->speed) {
        case 10: /* 10BASE */
-               sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_ELB, ECMR);
+               sh_eth_modify(ndev, ECMR, ECMR_ELB, 0);
                break;
        case 100:/* 100BASE */
-               sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_ELB, ECMR);
-               break;
-       default:
+               sh_eth_modify(ndev, ECMR, ECMR_ELB, ECMR_ELB);
                break;
        }
 }
@@ -649,12 +649,10 @@ static void sh_eth_set_rate_sh7724(struct net_device *ndev)
 
        switch (mdp->speed) {
        case 10: /* 10BASE */
-               sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR);
+               sh_eth_modify(ndev, ECMR, ECMR_RTM, 0);
                break;
        case 100:/* 100BASE */
-               sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR);
-               break;
-       default:
+               sh_eth_modify(ndev, ECMR, ECMR_RTM, ECMR_RTM);
                break;
        }
 }
@@ -694,8 +692,6 @@ static void sh_eth_set_rate_sh7757(struct net_device *ndev)
        case 100:/* 100BASE */
                sh_eth_write(ndev, 1, RTRATE);
                break;
-       default:
-               break;
        }
 }
 
@@ -763,8 +759,6 @@ static void sh_eth_set_rate_giga(struct net_device *ndev)
        case 1000: /* 1000BASE */
                sh_eth_write(ndev, 0x00000020, GECMR);
                break;
-       default:
-               break;
        }
 }
 
@@ -905,7 +899,7 @@ static int sh_eth_check_reset(struct net_device *ndev)
        int cnt = 100;
 
        while (cnt > 0) {
-               if (!(sh_eth_read(ndev, EDMR) & 0x3))
+               if (!(sh_eth_read(ndev, EDMR) & EDMR_SRST_GETHER))
                        break;
                mdelay(1);
                cnt--;
@@ -924,8 +918,7 @@ static int sh_eth_reset(struct net_device *ndev)
 
        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);
+               sh_eth_modify(ndev, EDMR, EDMR_SRST_GETHER, EDMR_SRST_GETHER);
 
                ret = sh_eth_check_reset(ndev);
                if (ret)
@@ -949,11 +942,9 @@ static int sh_eth_reset(struct net_device *ndev)
                if (mdp->cd->select_mii)
                        sh_eth_select_mii(ndev);
        } else {
-               sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER,
-                            EDMR);
+               sh_eth_modify(ndev, EDMR, EDMR_SRST_ETHER, EDMR_SRST_ETHER);
                mdelay(3);
-               sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER,
-                            EDMR);
+               sh_eth_modify(ndev, EDMR, EDMR_SRST_ETHER, 0);
        }
 
        return ret;
@@ -1136,11 +1127,8 @@ static void sh_eth_ring_format(struct net_device *ndev)
                        break;
                sh_eth_set_receive_align(skb);
 
-               /* RX descriptor */
-               rxdesc = &mdp->rx_ring[i];
                /* The size of the buffer is a multiple of 32 bytes. */
                buf_len = ALIGN(mdp->rx_buf_sz, 32);
-               rxdesc->len = cpu_to_le32(buf_len << 16);
                dma_addr = dma_map_single(&ndev->dev, skb->data, buf_len,
                                          DMA_FROM_DEVICE);
                if (dma_mapping_error(&ndev->dev, dma_addr)) {
@@ -1148,6 +1136,10 @@ static void sh_eth_ring_format(struct net_device *ndev)
                        break;
                }
                mdp->rx_skbuff[i] = skb;
+
+               /* RX descriptor */
+               rxdesc = &mdp->rx_ring[i];
+               rxdesc->len = cpu_to_le32(buf_len << 16);
                rxdesc->addr = cpu_to_le32(dma_addr);
                rxdesc->status = cpu_to_le32(RD_RACT | RD_RFP);
 
@@ -1163,7 +1155,8 @@ static void sh_eth_ring_format(struct net_device *ndev)
        mdp->dirty_rx = (u32) (i - mdp->num_rx_ring);
 
        /* Mark the last entry as wrapping the ring. */
-       rxdesc->status |= cpu_to_le32(RD_RDLE);
+       if (rxdesc)
+               rxdesc->status |= cpu_to_le32(RD_RDLE);
 
        memset(mdp->tx_ring, 0, tx_ringsize);
 
@@ -1236,10 +1229,10 @@ ring_free:
        return -ENOMEM;
 }
 
-static int sh_eth_dev_init(struct net_device *ndev, bool start)
+static int sh_eth_dev_init(struct net_device *ndev)
 {
-       int ret = 0;
        struct sh_eth_private *mdp = netdev_priv(ndev);
+       int ret;
 
        /* Soft Reset */
        ret = sh_eth_reset(ndev);
@@ -1285,11 +1278,9 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start)
        sh_eth_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN,
                     RFLR);
 
-       sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);
-       if (start) {
-               mdp->irq_enabled = true;
-               sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
-       }
+       sh_eth_modify(ndev, EESR, 0, 0);
+       mdp->irq_enabled = true;
+       sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
 
        /* PAUSE Prohibition */
        sh_eth_write(ndev, ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) |
@@ -1302,8 +1293,7 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start)
        sh_eth_write(ndev, mdp->cd->ecsr_value, ECSR);
 
        /* E-MAC Interrupt Enable register */
-       if (start)
-               sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR);
+       sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR);
 
        /* Set MAC address */
        update_mac_address(ndev);
@@ -1316,12 +1306,8 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start)
        if (mdp->cd->tpauser)
                sh_eth_write(ndev, TPAUSER_UNLIMITED, TPAUSER);
 
-       if (start) {
-               /* Setting the Rx mode will start the Rx process. */
-               sh_eth_write(ndev, EDRRR_R, EDRRR);
-
-               netif_start_queue(ndev);
-       }
+       /* Setting the Rx mode will start the Rx process. */
+       sh_eth_write(ndev, EDRRR_R, EDRRR);
 
        return ret;
 }
@@ -1362,7 +1348,7 @@ static int sh_eth_txfree(struct net_device *ndev)
        struct sh_eth_private *mdp = netdev_priv(ndev);
        struct sh_eth_txdesc *txdesc;
        int free_num = 0;
-       int entry = 0;
+       int entry;
 
        for (; mdp->cur_tx - mdp->dirty_tx > 0; mdp->dirty_tx++) {
                entry = mdp->dirty_tx % mdp->num_tx_ring;
@@ -1403,10 +1389,10 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
        int boguscnt = (mdp->dirty_rx + mdp->num_rx_ring) - mdp->cur_rx;
        int limit;
        struct sk_buff *skb;
-       u16 pkt_len = 0;
        u32 desc_status;
        int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1;
        dma_addr_t dma_addr;
+       u16 pkt_len;
        u32 buf_len;
 
        boguscnt = min(boguscnt, *quota);
@@ -1532,15 +1518,13 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
 static void sh_eth_rcv_snd_disable(struct net_device *ndev)
 {
        /* disable tx and rx */
-       sh_eth_write(ndev, sh_eth_read(ndev, ECMR) &
-               ~(ECMR_RE | ECMR_TE), ECMR);
+       sh_eth_modify(ndev, ECMR, ECMR_RE | ECMR_TE, 0);
 }
 
 static void sh_eth_rcv_snd_enable(struct net_device *ndev)
 {
        /* enable tx and rx */
-       sh_eth_write(ndev, sh_eth_read(ndev, ECMR) |
-               (ECMR_RE | ECMR_TE), ECMR);
+       sh_eth_modify(ndev, ECMR, ECMR_RE | ECMR_TE, ECMR_RE | ECMR_TE);
 }
 
 /* error control function */
@@ -1569,13 +1553,11 @@ static void sh_eth_error(struct net_device *ndev, u32 intr_status)
                                sh_eth_rcv_snd_disable(ndev);
                        } else {
                                /* Link Up */
-                               sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) &
-                                                  ~DMAC_M_ECI, EESIPR);
+                               sh_eth_modify(ndev, EESIPR, DMAC_M_ECI, 0);
                                /* clear int */
-                               sh_eth_write(ndev, sh_eth_read(ndev, ECSR),
-                                            ECSR);
-                               sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) |
-                                                  DMAC_M_ECI, EESIPR);
+                               sh_eth_modify(ndev, ECSR, 0, 0);
+                               sh_eth_modify(ndev, EESIPR, DMAC_M_ECI,
+                                             DMAC_M_ECI);
                                /* enable tx and rx */
                                sh_eth_rcv_snd_enable(ndev);
                        }
@@ -1765,9 +1747,7 @@ static void sh_eth_adjust_link(struct net_device *ndev)
                                mdp->cd->set_rate(ndev);
                }
                if (!mdp->link) {
-                       sh_eth_write(ndev,
-                                    sh_eth_read(ndev, ECMR) & ~ECMR_TXF,
-                                    ECMR);
+                       sh_eth_modify(ndev, ECMR, ECMR_TXF, 0);
                        new_state = 1;
                        mdp->link = phydev->link;
                        if (mdp->cd->no_psr || mdp->no_ether_link)
@@ -1791,7 +1771,7 @@ 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);
-       struct phy_device *phydev = NULL;
+       struct phy_device *phydev;
 
        mdp->link = 0;
        mdp->speed = 0;
@@ -2209,17 +2189,13 @@ static int sh_eth_set_ringparam(struct net_device *ndev,
                                   __func__);
                        return ret;
                }
-               ret = sh_eth_dev_init(ndev, false);
+               ret = sh_eth_dev_init(ndev);
                if (ret < 0) {
                        netdev_err(ndev, "%s: sh_eth_dev_init failed.\n",
                                   __func__);
                        return ret;
                }
 
-               mdp->irq_enabled = true;
-               sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
-               /* Setting the Rx mode will start the Rx process. */
-               sh_eth_write(ndev, EDRRR_R, EDRRR);
                netif_device_attach(ndev);
        }
 
@@ -2245,8 +2221,8 @@ static const struct ethtool_ops sh_eth_ethtool_ops = {
 /* network device open function */
 static int sh_eth_open(struct net_device *ndev)
 {
-       int ret = 0;
        struct sh_eth_private *mdp = netdev_priv(ndev);
+       int ret;
 
        pm_runtime_get_sync(&mdp->pdev->dev);
 
@@ -2265,7 +2241,7 @@ static int sh_eth_open(struct net_device *ndev)
                goto out_free_irq;
 
        /* device init */
-       ret = sh_eth_dev_init(ndev, true);
+       ret = sh_eth_dev_init(ndev);
        if (ret)
                goto out_free_irq;
 
@@ -2274,6 +2250,8 @@ static int sh_eth_open(struct net_device *ndev)
        if (ret)
                goto out_free_irq;
 
+       netif_start_queue(ndev);
+
        mdp->is_opened = 1;
 
        return ret;
@@ -2316,7 +2294,9 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
        }
 
        /* device init */
-       sh_eth_dev_init(ndev, true);
+       sh_eth_dev_init(ndev);
+
+       netif_start_queue(ndev);
 }
 
 /* Packet transmit function */
@@ -2922,8 +2902,6 @@ static const u16 *sh_eth_get_register_offset(int register_type)
        case SH_ETH_REG_FAST_SH3_SH2:
                reg_offset = sh_eth_offset_fast_sh3_sh2;
                break;
-       default:
-               break;
        }
 
        return reg_offset;
@@ -3003,12 +2981,12 @@ static inline struct sh_eth_plat_data *sh_eth_parse_dt(struct device *dev)
 
 static int sh_eth_drv_probe(struct platform_device *pdev)
 {
-       int ret, devno = 0;
        struct resource *res;
-       struct net_device *ndev = NULL;
-       struct sh_eth_private *mdp = NULL;
        struct sh_eth_plat_data *pd = dev_get_platdata(&pdev->dev);
        const struct platform_device_id *id = platform_get_device_id(pdev);
+       struct sh_eth_private *mdp;
+       struct net_device *ndev;
+       int ret, devno;
 
        /* get base addr */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);