aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/renesas/sh_eth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/renesas/sh_eth.c')
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c109
1 files changed, 46 insertions, 63 deletions
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index dfa9e59c9442..004e2d7560fd 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -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;
}
}
@@ -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);
@@ -1238,8 +1231,8 @@ ring_free:
static int sh_eth_dev_init(struct net_device *ndev, bool start)
{
- int ret = 0;
struct sh_eth_private *mdp = netdev_priv(ndev);
+ int ret;
/* Soft Reset */
ret = sh_eth_reset(ndev);
@@ -1285,7 +1278,7 @@ 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);
+ sh_eth_modify(ndev, EESR, 0, 0);
if (start) {
mdp->irq_enabled = true;
sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
@@ -1319,8 +1312,6 @@ static int sh_eth_dev_init(struct net_device *ndev, bool start)
if (start) {
/* Setting the Rx mode will start the Rx process. */
sh_eth_write(ndev, EDRRR_R, EDRRR);
-
- netif_start_queue(ndev);
}
return ret;
@@ -1362,7 +1353,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 +1394,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 +1523,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 +1558,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 +1752,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 +1776,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;
@@ -2245,8 +2230,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);
@@ -2274,6 +2259,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;
@@ -2317,6 +2304,8 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
/* device init */
sh_eth_dev_init(ndev, true);
+
+ netif_start_queue(ndev);
}
/* Packet transmit function */
@@ -2922,8 +2911,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 +2990,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);
@@ -3061,15 +3048,11 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
mdp->ether_link_active_low = pd->ether_link_active_low;
/* set cpu data */
- if (id) {
+ if (id)
mdp->cd = (struct sh_eth_cpu_data *)id->driver_data;
- } else {
- const struct of_device_id *match;
+ else
+ mdp->cd = (struct sh_eth_cpu_data *)of_device_get_match_data(&pdev->dev);
- 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",