static int xgbe_phy_reset(struct xgbe_prv_data *pdata) { unsigned int count, reg; reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); reg |= MDIO_CTRL1_RESET; XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); count = 50; do { msleep(20); reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); } while ((reg & MDIO_CTRL1_RESET) && --count); if (reg & MDIO_CTRL1_RESET) return -ETIMEDOUT; /* Disable auto-negotiation for now */ xgbe_disable_an(pdata); /* Clear auto-negotiation interrupts */ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); return 0; }
static irqreturn_t xgbe_an_isr(int irq, void *data) { struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n"); /* Disable AN interrupts */ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0); /* Save the interrupt(s) that fired */ pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT); if (pdata->an_int) { /* Clear the interrupt(s) that fired and process them */ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int); queue_work(pdata->an_workqueue, &pdata->an_irq_work); } else { /* Enable AN interrupts */ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_INT_MASK); } return IRQ_HANDLED; }
static void axgbe_an37_disable_interrupts(struct axgbe_port *pdata) { int reg; reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL); reg &= ~AXGBE_AN_CL37_INT_MASK; XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg); reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL); reg &= ~AXGBE_PCS_CL37_BP; XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg); }
static void xgbe_an37_enable_interrupts(struct xgbe_prv_data *pdata) { int reg; reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL); reg |= XGBE_PCS_CL37_BP; XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg); reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL); reg |= XGBE_AN_CL37_INT_MASK; XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg); }
static void xgbe_pcs_power_cycle(struct xgbe_prv_data *pdata) { unsigned int reg; reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); reg |= MDIO_CTRL1_LPOWER; XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); usleep_range(75, 100); reg &= ~MDIO_CTRL1_LPOWER; XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); }
static void xgbe_an73_init(struct xgbe_prv_data *pdata) { unsigned int advertising, reg; advertising = pdata->phy_if.phy_impl.an_advertising(pdata); /* Set up Advertisement register 3 first */ reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); if (advertising & ADVERTISED_10000baseR_FEC) reg |= 0xc000; else reg &= ~0xc000; XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2, reg); /* Set up Advertisement register 2 next */ reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); if (advertising & ADVERTISED_10000baseKR_Full) reg |= 0x80; else reg &= ~0x80; if ((advertising & ADVERTISED_1000baseKX_Full) || (advertising & ADVERTISED_2500baseX_Full)) reg |= 0x20; else reg &= ~0x20; XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1, reg); /* Set up Advertisement register 1 last */ reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE); if (advertising & ADVERTISED_Pause) reg |= 0x400; else reg &= ~0x400; if (advertising & ADVERTISED_Asym_Pause) reg |= 0x800; else reg &= ~0x800; /* We don't intend to perform XNP */ reg &= ~XGBE_XNP_NP_EXCHANGE; XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); netif_dbg(pdata, link, pdata->netdev, "CL73 AN initialized\n"); }
static enum xgbe_an xgbe_an73_tx_xnp(struct xgbe_prv_data *pdata, enum xgbe_rx *state) { u16 msg; *state = XGBE_RX_XNP; msg = XGBE_XNP_MCF_NULL_MESSAGE; msg |= XGBE_XNP_MP_FORMATTED; XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP + 2, 0); XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP + 1, 0); XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP, msg); return XGBE_AN_PAGE_RECEIVED; }
static void xgbe_gmii_mode(struct xgbe_prv_data *pdata) { unsigned int reg; /* Disable KR training */ xgbe_an_disable_kr_training(pdata); /* Set MAC to 1G speed */ pdata->hw_if.set_gmii_speed(pdata); /* Set PCS to KX/1G speed */ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); reg &= ~MDIO_PCS_CTRL2_TYPE; reg |= MDIO_PCS_CTRL2_10GBX; XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg); reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); reg &= ~MDIO_CTRL1_SPEEDSEL; reg |= MDIO_CTRL1_SPEED1G; XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); xgbe_pcs_power_cycle(pdata); /* Set SerDes to 1G speed */ xgbe_serdes_start_ratechange(pdata); XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE); XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD); XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL); XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE, pdata->serdes_cdr_rate[XGBE_SPEED_1000]); XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP, pdata->serdes_tx_amp[XGBE_SPEED_1000]); XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA, pdata->serdes_blwc[XGBE_SPEED_1000]); XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG, pdata->serdes_pq_skew[XGBE_SPEED_1000]); XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG, pdata->serdes_dfe_tap_cfg[XGBE_SPEED_1000]); XRXTX_IOWRITE(pdata, RXTX_REG22, pdata->serdes_dfe_tap_ena[XGBE_SPEED_1000]); xgbe_serdes_complete_ratechange(pdata); netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n"); }
static void xgbe_an37_clear_interrupts(struct xgbe_prv_data *pdata) { int reg; reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT); reg &= ~XGBE_AN_CL37_INT_MASK; XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg); }
static void xgbe_an37_init(struct xgbe_prv_data *pdata) { unsigned int advertising, reg; advertising = pdata->phy_if.phy_impl.an_advertising(pdata); /* Set up Advertisement register */ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE); if (advertising & ADVERTISED_Pause) reg |= 0x100; else reg &= ~0x100; if (advertising & ADVERTISED_Asym_Pause) reg |= 0x80; else reg &= ~0x80; /* Full duplex, but not half */ reg |= XGBE_AN_CL37_FD_MASK; reg &= ~XGBE_AN_CL37_HD_MASK; XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE, reg); /* Set up the Control register */ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL); reg &= ~XGBE_AN_CL37_TX_CONFIG_MASK; reg &= ~XGBE_AN_CL37_PCS_MODE_MASK; switch (pdata->an_mode) { case XGBE_AN_MODE_CL37: reg |= XGBE_AN_CL37_PCS_MODE_BASEX; break; case XGBE_AN_MODE_CL37_SGMII: reg |= XGBE_AN_CL37_PCS_MODE_SGMII; break; default: break; } XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg); netif_dbg(pdata, link, pdata->netdev, "CL37 AN (%s) initialized\n", (pdata->an_mode == XGBE_AN_MODE_CL37) ? "BaseX" : "SGMII"); }
static void axgbe_an73_enable_kr_training(struct axgbe_port *pdata) { unsigned int reg; reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL); reg |= AXGBE_KR_TRAINING_ENABLE; XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg); }
static void xgbe_an73_disable_kr_training(struct xgbe_prv_data *pdata) { unsigned int reg; reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL); reg &= ~XGBE_KR_TRAINING_ENABLE; XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg); }
static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata, enum xgbe_rx *state) { unsigned int ad_reg, lp_reg, reg; *state = XGBE_RX_COMPLETE; /* If we're not in KR mode then we're done */ if (!xgbe_in_kr_mode(pdata)) return XGBE_AN_PAGE_RECEIVED; /* Enable/Disable FEC */ ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL); reg &= ~(MDIO_PMA_10GBR_FECABLE_ABLE | MDIO_PMA_10GBR_FECABLE_ERRABLE); if ((ad_reg & 0xc000) && (lp_reg & 0xc000)) reg |= pdata->fec_ability; XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL, reg); /* Start KR training */ reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL); if (reg & XGBE_KR_TRAINING_ENABLE) { if (pdata->phy_if.phy_impl.kr_training_pre) pdata->phy_if.phy_impl.kr_training_pre(pdata); reg |= XGBE_KR_TRAINING_START; XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg); if (pdata->phy_if.phy_impl.kr_training_post) pdata->phy_if.phy_impl.kr_training_post(pdata); netif_dbg(pdata, link, pdata->netdev, "KR training initiated\n"); } return XGBE_AN_PAGE_RECEIVED; }
static int xgbe_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct xgbe_prv_data *pdata = pci_get_drvdata(pdev); struct net_device *netdev = pdata->netdev; int ret = 0; if (netif_running(netdev)) ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT); pdata->lpm_ctrl = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); pdata->lpm_ctrl |= MDIO_CTRL1_LPOWER; XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl); return ret; }
static void xgbe_set_an(struct xgbe_prv_data *pdata, bool enable, bool restart) { unsigned int reg; reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1); reg &= ~MDIO_AN_CTRL1_ENABLE; if (enable) reg |= MDIO_AN_CTRL1_ENABLE; if (restart) reg |= MDIO_AN_CTRL1_RESTART; XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_CTRL1, reg); }
static void axgbe_an37_set(struct axgbe_port *pdata, bool enable, bool restart) { unsigned int reg; reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_CTRL1); reg &= ~MDIO_VEND2_CTRL1_AN_ENABLE; if (enable) reg |= MDIO_VEND2_CTRL1_AN_ENABLE; if (restart) reg |= MDIO_VEND2_CTRL1_AN_RESTART; XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg); }
static ssize_t xpcs_reg_value_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos) { struct xgbe_prv_data *pdata = filp->private_data; unsigned int value; ssize_t len; len = xgbe_common_write(buffer, count, ppos, &value); if (len < 0) return len; XMDIO_WRITE(pdata, pdata->debugfs_xpcs_mmd, pdata->debugfs_xpcs_reg, value); return len; }
static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) { set_bit(XGBE_LINK_INIT, &pdata->dev_state); pdata->link_check = jiffies; if (pdata->phy.autoneg != AUTONEG_ENABLE) return xgbe_phy_config_fixed(pdata); netif_dbg(pdata, link, pdata->netdev, "AN PHY configuration\n"); /* Disable auto-negotiation interrupt */ disable_irq(pdata->an_irq); /* Start auto-negotiation in a supported mode */ if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full) { xgbe_set_mode(pdata, XGBE_MODE_KR); } else if ((pdata->phy.advertising & ADVERTISED_1000baseKX_Full) || (pdata->phy.advertising & ADVERTISED_2500baseX_Full)) { xgbe_set_mode(pdata, XGBE_MODE_KX); } else { enable_irq(pdata->an_irq); return -EINVAL; } /* Disable and stop any in progress auto-negotiation */ xgbe_disable_an(pdata); /* Clear any auto-negotitation interrupts */ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); pdata->an_result = XGBE_AN_READY; pdata->an_state = XGBE_AN_READY; pdata->kr_state = XGBE_RX_BPA; pdata->kx_state = XGBE_RX_BPA; /* Re-enable auto-negotiation interrupt */ enable_irq(pdata->an_irq); /* Set up advertisement registers based on current settings */ xgbe_an_init(pdata); /* Enable and start auto-negotiation */ xgbe_restart_an(pdata); return 0; }
static void xgbe_phy_stop(struct xgbe_prv_data *pdata) { netif_dbg(pdata, link, pdata->netdev, "stopping PHY\n"); /* Disable auto-negotiation */ xgbe_disable_an(pdata); /* Disable auto-negotiation interrupts */ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0); devm_free_irq(pdata->dev, pdata->an_irq, pdata); pdata->phy.link = 0; netif_carrier_off(pdata->netdev); xgbe_phy_adjust_link(pdata); }
static int xgbe_resume(struct device *dev) { struct net_device *netdev = dev_get_drvdata(dev); struct xgbe_prv_data *pdata = netdev_priv(netdev); int ret = 0; DBGPR("-->xgbe_resume\n"); pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER; XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl); if (netif_running(netdev)) ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT); DBGPR("<--xgbe_resume\n"); return ret; }
static void xgbe_an73_isr(struct xgbe_prv_data *pdata) { /* Disable AN interrupts */ xgbe_an73_disable_interrupts(pdata); /* Save the interrupt(s) that fired */ pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT); if (pdata->an_int) { /* Clear the interrupt(s) that fired and process them */ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int); queue_work(pdata->an_workqueue, &pdata->an_irq_work); } else { /* Enable AN interrupts */ xgbe_an73_enable_interrupts(pdata); } }
static void axgbe_an73_isr(struct axgbe_port *pdata) { /* Disable AN interrupts */ axgbe_an73_disable_interrupts(pdata); /* Save the interrupt(s) that fired */ pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT); if (pdata->an_int) { /* Clear the interrupt(s) that fired and process them */ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int); pthread_mutex_lock(&pdata->an_mutex); axgbe_an73_state_machine(pdata); pthread_mutex_unlock(&pdata->an_mutex); } else { /* Enable AN interrupts */ axgbe_an73_enable_interrupts(pdata); } }
static int xgbe_phy_start(struct xgbe_prv_data *pdata) { struct net_device *netdev = pdata->netdev; int ret; netif_dbg(pdata, link, pdata->netdev, "starting PHY\n"); ret = devm_request_irq(pdata->dev, pdata->an_irq, xgbe_an_isr, 0, pdata->an_name, pdata); if (ret) { netdev_err(netdev, "phy irq request failed\n"); return ret; } /* Set initial mode - call the mode setting routines * directly to insure we are properly configured */ if (xgbe_use_xgmii_mode(pdata)) { xgbe_xgmii_mode(pdata); } else if (xgbe_use_gmii_mode(pdata)) { xgbe_gmii_mode(pdata); } else if (xgbe_use_gmii_2500_mode(pdata)) { xgbe_gmii_2500_mode(pdata); } else { ret = -EINVAL; goto err_irq; } /* Set up advertisement registers based on current settings */ xgbe_an_init(pdata); /* Enable auto-negotiation interrupts */ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0x07); return xgbe_phy_config_aneg(pdata); err_irq: devm_free_irq(pdata->dev, pdata->an_irq, pdata); return ret; }
static int xgbe_pci_resume(struct pci_dev *pdev) { struct xgbe_prv_data *pdata = pci_get_drvdata(pdev); struct net_device *netdev = pdata->netdev; int ret = 0; pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER; XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl); if (netif_running(netdev)) { ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT); /* Schedule a restart in case the link or phy state changed * while we were powered down. */ schedule_work(&pdata->restart_work); } return ret; }
static void xgbe_an37_isr(struct xgbe_prv_data *pdata) { unsigned int reg; /* Disable AN interrupts */ xgbe_an37_disable_interrupts(pdata); /* Save the interrupt(s) that fired */ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT); pdata->an_int = reg & XGBE_AN_CL37_INT_MASK; pdata->an_status = reg & ~XGBE_AN_CL37_INT_MASK; if (pdata->an_int) { /* Clear the interrupt(s) that fired and process them */ reg &= ~XGBE_AN_CL37_INT_MASK; XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg); queue_work(pdata->an_workqueue, &pdata->an_irq_work); } else { /* Enable AN interrupts */ xgbe_an37_enable_interrupts(pdata); } }
static void xgbe_an_state_machine(struct work_struct *work) { struct xgbe_prv_data *pdata = container_of(work, struct xgbe_prv_data, an_work); enum xgbe_an cur_state = pdata->an_state; unsigned int int_reg, int_mask; mutex_lock(&pdata->an_mutex); /* Read the interrupt */ int_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT); if (!int_reg) goto out; next_int: if (int_reg & XGBE_AN_PG_RCV) { pdata->an_state = XGBE_AN_PAGE_RECEIVED; int_mask = XGBE_AN_PG_RCV; } else if (int_reg & XGBE_AN_INC_LINK) { pdata->an_state = XGBE_AN_INCOMPAT_LINK; int_mask = XGBE_AN_INC_LINK; } else if (int_reg & XGBE_AN_INT_CMPLT) { pdata->an_state = XGBE_AN_COMPLETE; int_mask = XGBE_AN_INT_CMPLT; } else { pdata->an_state = XGBE_AN_ERROR; int_mask = 0; } /* Clear the interrupt to be processed */ int_reg &= ~int_mask; XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, int_reg); pdata->an_result = pdata->an_state; again: netif_dbg(pdata, link, pdata->netdev, "AN %s\n", xgbe_state_as_string(pdata->an_state)); cur_state = pdata->an_state; switch (pdata->an_state) { case XGBE_AN_READY: pdata->an_supported = 0; break; case XGBE_AN_PAGE_RECEIVED: pdata->an_state = xgbe_an_page_received(pdata); pdata->an_supported++; break; case XGBE_AN_INCOMPAT_LINK: pdata->an_supported = 0; pdata->parallel_detect = 0; pdata->an_state = xgbe_an_incompat_link(pdata); break; case XGBE_AN_COMPLETE: pdata->parallel_detect = pdata->an_supported ? 0 : 1; netif_dbg(pdata, link, pdata->netdev, "%s successful\n", pdata->an_supported ? "Auto negotiation" : "Parallel detection"); break; case XGBE_AN_NO_LINK: break; default: pdata->an_state = XGBE_AN_ERROR; } if (pdata->an_state == XGBE_AN_NO_LINK) { int_reg = 0; XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); } else if (pdata->an_state == XGBE_AN_ERROR) { netdev_err(pdata->netdev, "error during auto-negotiation, state=%u\n", cur_state); int_reg = 0; XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); } if (pdata->an_state >= XGBE_AN_COMPLETE) { pdata->an_result = pdata->an_state; pdata->an_state = XGBE_AN_READY; pdata->kr_state = XGBE_RX_BPA; pdata->kx_state = XGBE_RX_BPA; pdata->an_start = 0; netif_dbg(pdata, link, pdata->netdev, "AN result: %s\n", xgbe_state_as_string(pdata->an_result)); } if (cur_state != pdata->an_state) goto again; if (int_reg) goto next_int; out: enable_irq(pdata->an_irq); mutex_unlock(&pdata->an_mutex); }
static void axgbe_an73_enable_interrupts(struct axgbe_port *pdata) { XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, AXGBE_AN_CL73_INT_MASK); }
static void xgbe_an73_enable_interrupts(struct xgbe_prv_data *pdata) { XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_CL73_INT_MASK); }
static void xgbe_an73_disable_interrupts(struct xgbe_prv_data *pdata) { XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0); }
static void xgbe_an73_clear_interrupts(struct xgbe_prv_data *pdata) { XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0); }