diff options
Diffstat (limited to 'drivers/net/ethernet/renesas')
-rw-r--r-- | drivers/net/ethernet/renesas/sh_eth.c | 103 | ||||
-rw-r--r-- | drivers/net/ethernet/renesas/sh_eth.h | 2 |
2 files changed, 53 insertions, 52 deletions
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index f729a6b43958..9a97cb13029a 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1,9 +1,9 @@ /* SuperH Ethernet device driver * - * Copyright (C) 2014 Renesas Electronics Corporation + * Copyright (C) 2014 Renesas Electronics Corporation * Copyright (C) 2006-2012 Nobuhiro Iwamatsu * Copyright (C) 2008-2014 Renesas Solutions Corp. - * Copyright (C) 2013-2016 Cogent Embedded, Inc. + * Copyright (C) 2013-2017 Cogent Embedded, Inc. * Copyright (C) 2014 Codethink Limited * * This program is free software; you can redistribute it and/or modify it @@ -523,7 +523,7 @@ static struct sh_eth_cpu_data r7s72100_data = { .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, + EESR_TDE, .fdr_value = 0x0000070f, .no_psr = 1, @@ -562,7 +562,7 @@ static struct sh_eth_cpu_data r8a7740_data = { .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, + EESR_TDE, .fdr_value = 0x0000070f, .apr = 1, @@ -608,8 +608,7 @@ static struct sh_eth_cpu_data r8a777x_data = { .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | - EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | - EESR_ECI, + EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE, .fdr_value = 0x00000f0f, .apr = 1, @@ -631,8 +630,7 @@ static struct sh_eth_cpu_data r8a779x_data = { .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | - EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | - EESR_ECI, + EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE, .fdr_value = 0x00000f0f, .trscer_err_mask = DESC_I_RINT8, @@ -672,8 +670,7 @@ static struct sh_eth_cpu_data sh7724_data = { .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | - EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | - EESR_ECI, + EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE, .apr = 1, .mpr = 1, @@ -708,8 +705,7 @@ static struct sh_eth_cpu_data sh7757_data = { .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | - EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | - EESR_ECI, + EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE, .irq_flags = IRQF_SHARED, .apr = 1, @@ -777,7 +773,7 @@ static struct sh_eth_cpu_data sh7757_data_giga = { .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, + EESR_TDE, .fdr_value = 0x0000072f, .irq_flags = IRQF_SHARED, @@ -808,7 +804,7 @@ static struct sh_eth_cpu_data sh7734_data = { .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, + EESR_TDE, .apr = 1, .mpr = 1, @@ -837,8 +833,7 @@ static struct sh_eth_cpu_data sh7763_data = { .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_ECI, + EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE, .apr = 1, .mpr = 1, @@ -1528,44 +1523,44 @@ static void sh_eth_rcv_snd_enable(struct net_device *ndev) sh_eth_modify(ndev, ECMR, ECMR_RE | ECMR_TE, ECMR_RE | ECMR_TE); } -/* error control function */ -static void sh_eth_error(struct net_device *ndev, u32 intr_status) +/* E-MAC interrupt handler */ +static void sh_eth_emac_interrupt(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); u32 felic_stat; u32 link_stat; - u32 mask; - if (intr_status & EESR_ECI) { - felic_stat = sh_eth_read(ndev, ECSR); - sh_eth_write(ndev, felic_stat, ECSR); /* clear int */ - if (felic_stat & ECSR_ICD) - ndev->stats.tx_carrier_errors++; - if (felic_stat & ECSR_LCHNG) { - /* Link Changed */ - if (mdp->cd->no_psr || mdp->no_ether_link) { - goto ignore_link; - } else { - link_stat = (sh_eth_read(ndev, PSR)); - if (mdp->ether_link_active_low) - link_stat = ~link_stat; - } - if (!(link_stat & PHY_ST_LINK)) { - sh_eth_rcv_snd_disable(ndev); - } else { - /* Link Up */ - sh_eth_modify(ndev, EESIPR, DMAC_M_ECI, 0); - /* clear int */ - 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); - } + felic_stat = sh_eth_read(ndev, ECSR) & sh_eth_read(ndev, ECSIPR); + sh_eth_write(ndev, felic_stat, ECSR); /* clear int */ + if (felic_stat & ECSR_ICD) + ndev->stats.tx_carrier_errors++; + if (felic_stat & ECSR_LCHNG) { + /* Link Changed */ + if (mdp->cd->no_psr || mdp->no_ether_link) + return; + link_stat = sh_eth_read(ndev, PSR); + if (mdp->ether_link_active_low) + link_stat = ~link_stat; + if (!(link_stat & PHY_ST_LINK)) { + sh_eth_rcv_snd_disable(ndev); + } else { + /* Link Up */ + sh_eth_modify(ndev, EESIPR, DMAC_M_ECI, 0); + /* clear int */ + 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); } } +} + +/* error control function */ +static void sh_eth_error(struct net_device *ndev, u32 intr_status) +{ + struct sh_eth_private *mdp = netdev_priv(ndev); + u32 mask; -ignore_link: if (intr_status & EESR_TWB) { /* Unused write back interrupt */ if (intr_status & EESR_TABT) { /* Transmit Abort int */ @@ -1646,14 +1641,16 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) /* Get interrupt status */ intr_status = sh_eth_read(ndev, EESR); - /* Mask it with the interrupt mask, forcing ECI interrupt to be always - * enabled since it's the one that comes thru regardless of the mask, - * and we need to fully handle it in sh_eth_error() in order to quench - * it as it doesn't get cleared by just writing 1 to the ECI bit... + /* Mask it with the interrupt mask, forcing ECI interrupt to be always + * enabled since it's the one that comes thru regardless of the mask, + * and we need to fully handle it in sh_eth_emac_interrupt() in order + * to quench it as it doesn't get cleared by just writing 1 to the ECI + * bit... */ intr_enable = sh_eth_read(ndev, EESIPR); intr_status &= intr_enable | DMAC_M_ECI; - if (intr_status & (EESR_RX_CHECK | cd->tx_check | cd->eesr_err_check)) + if (intr_status & (EESR_RX_CHECK | cd->tx_check | EESR_ECI | + cd->eesr_err_check)) ret = IRQ_HANDLED; else goto out; @@ -1685,6 +1682,10 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) netif_wake_queue(ndev); } + /* E-MAC interrupt */ + if (intr_status & EESR_ECI) + sh_eth_emac_interrupt(ndev); + if (intr_status & cd->eesr_err_check) { /* Clear error interrupts */ sh_eth_write(ndev, intr_status & cd->eesr_err_check, EESR); diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index d050f37f3e0f..9eec1e185adf 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -265,7 +265,7 @@ enum EESR_BIT { EESR_RTO) #define DEFAULT_EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | \ EESR_RDE | EESR_RFRMER | EESR_ADE | \ - EESR_TFE | EESR_TDE | EESR_ECI) + EESR_TFE | EESR_TDE) /* EESIPR */ enum DMAC_IM_BIT { |