/* Auto-Configure this MII interface */ static MII_CONFIG mii_autoconfigure(struct net_device *dev) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); int i; int val; MII_CONFIG eConfig; TRACE(("mii_autoconfigure\n")); /* enable and restart autonegotiation */ val = mii_read(dev, pDevCtrl->EnetInfo.ucPhyAddress, MII_BMCR); val |= (BMCR_ANRESTART | BMCR_ANENABLE); mii_write(dev, pDevCtrl->EnetInfo.ucPhyAddress, MII_BMCR, val); /* wait for it to finish */ for (i = 0; i < 1000; i++) { mdelay(1); val = mii_read(dev, pDevCtrl->EnetInfo.ucPhyAddress, MII_BMSR); if (val & BMSR_ANEGCOMPLETE) { break; } } eConfig = mii_getconfig(dev); if (val & BMSR_ANEGCOMPLETE) { eConfig |= MII_AUTONEG; } return eConfig; }
/* Auto-Configure this MII interface */ static MII_CONFIG * mii_autoconfigure(struct net_device *dev) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); int i; int val; MII_CONFIG * config = NULL; TRACE(("mii_autoconfigure, PhyAddress=0x%x\n", pDevCtrl->EnetInfo.PhyAddress)); /* TODO set advertise register */ /* enable and restart autonegotiation */ val = mii_read(dev, pDevCtrl->EnetInfo.PhyAddress, MII_BMCR); val |= (BMCR_ANRESTART | BMCR_ANENABLE); mii_write(dev, pDevCtrl->EnetInfo.PhyAddress, MII_BMCR, val); /* wait for it to finish */ for (i = 0; i < 400; i++) { if (pDevCtrl->mii_pid != 0) { /* we are in thread, we can go into sleep.*/ msleep(10); }else { mdelay(10); } val = mii_read(dev, pDevCtrl->EnetInfo.PhyAddress, MII_BMSR); #if defined(CONFIG_BCM5325_SWITCH) && (CONFIG_BCM5325_SWITCH == 1) if ((val & BMSR_ANEGCOMPLETE) || ((val & BMSR_LSTATUS) == 0)) { #else if (val & BMSR_ANEGCOMPLETE) { #endif break; } } if(i == 400) TRACE(("Auto-nego timedout!\n")); else TRACE(("Auto-nego completed, BMSR=0x%x\n", val)); config = mii_getconfig(dev); if( (config != NULL) && (val & BMSR_ANEGCOMPLETE) ) { config->auto_ne = 1; } return config; } /* * restart auto-negotiation, config UMAC and RGMII block */ void mii_setup(struct net_device *dev) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); volatile uniMacRegs * umac = pDevCtrl->umac; volatile rbufRegs * txrx_ctrl = pDevCtrl->txrx_ctrl; MII_CONFIG * eMiiConfig = NULL; eMiiConfig = mii_autoconfigure(dev); if ( !eMiiConfig || !eMiiConfig->auto_ne) { printk(KERN_WARNING " Auto-negotiation failed, forcing to default\n"); eMiiConfig = &g_mii_configs[3]; } printk("%s: %s\n", eMiiConfig->name, eMiiConfig->auto_ne == 1 ? "Auto-Neg":"Forced"); /* * program UMAC and RGMII block accordingly, if the PHY is * not capable of in-band signaling. */ umac->cmd &= ~CMD_HD_EN; if(pDevCtrl->EnetInfo.PhyType != BP_ENET_EXTERNAL_GPHY_IBS) { txrx_ctrl->rgmii_oob_ctrl &= ~OOB_DISABLE; txrx_ctrl->rgmii_oob_ctrl |= RGMII_LINK; /* pause control*/ if((eMiiConfig->pause & RX_PAUSE) == 0) umac->cmd |= CMD_RX_PAUSE_IGNORE; //umac->pause_ctrl |= PAUSE_CTRL_EN; else if ((eMiiConfig->pause & TX_PAUSE) == 0) umac->cmd |= CMD_TX_PAUSE_IGNORE; //umac->pause_ctrl &= ~PAUSE_CTRL_EN; /* duplex.*/ if(eMiiConfig->hcd == MII_BRCM_AUX_AN_HCD_10T || eMiiConfig->hcd == MII_BRCM_AUX_AN_HCD_100TX || eMiiConfig->hcd == LPA_1000HALF) { umac->cmd |= CMD_HD_EN; } /* speed */ umac->cmd = umac->cmd & ~(CMD_SPEED_MASK << CMD_SPEED_SHIFT); if(eMiiConfig->hcd == MII_BRCM_AUX_AN_HCD_10T || eMiiConfig->hcd == MII_BRCM_AUX_AN_HCD_10T_FULL) umac->cmd = umac->cmd | (UMAC_SPEED_10 << CMD_SPEED_SHIFT); else if (eMiiConfig->hcd == MII_BRCM_AUX_AN_HCD_100TX || eMiiConfig->hcd == MII_BRCM_AUX_AN_HCD_100TX_FULL) umac->cmd = umac->cmd | (UMAC_SPEED_100 << CMD_SPEED_SHIFT); else if (eMiiConfig->hcd == LPA_1000HALF || eMiiConfig->hcd == LPA_1000FULL) umac->cmd = umac->cmd | (UMAC_SPEED_1000 << CMD_SPEED_SHIFT); printk(KERN_WARNING "Link Parameters: %s\n", eMiiConfig->name); } #ifdef PHY_LOOPBACK /* Enable PHY loopback */ mii_loopback(dev); #endif }
/* Auto-Configure this MII interface */ static MII_CONFIG mii_autoconfigure(struct net_device *dev) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); int i; int val; MII_CONFIG eConfig; TRACE(("mii_autoconfigure\n")); /* enable and restart autonegotiation */ val = mii_read(dev, pDevCtrl->EnetInfo.ucPhyAddress, MII_BMCR); val |= (BMCR_ANRESTART | BMCR_ANENABLE); mii_write(dev, pDevCtrl->EnetInfo.ucPhyAddress, MII_BMCR, val); /* wait for it to finish */ for (i = 0; i < 2000; i++) { #if defined (CONFIG_MIPS_BCM_NDVD) msleep(1); #else mdelay(1); #endif val = mii_read(dev, pDevCtrl->EnetInfo.ucPhyAddress, MII_BMSR); #if defined(CONFIG_BCM5325_SWITCH) && (CONFIG_BCM5325_SWITCH == 1) if ((val & BMSR_ANEGCOMPLETE) || ((val & BMSR_LSTATUS) == 0)) { #else if (val & BMSR_ANEGCOMPLETE) { #endif break; } } eConfig = mii_getconfig(dev); if (val & BMSR_ANEGCOMPLETE) { eConfig |= MII_AUTONEG; } return eConfig; } static void mii_setup(struct net_device *dev) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); MII_CONFIG eMiiConfig; eMiiConfig = mii_autoconfigure(dev); if (! (eMiiConfig & MII_AUTONEG)) { printk(": Auto-negotiation timed-out\n"); } if ((eMiiConfig & (MII_100MBIT | MII_FULLDUPLEX)) == (MII_100MBIT | MII_FULLDUPLEX)) { printk(": 100 MB Full-Duplex (auto-neg)\n"); } else if (eMiiConfig & MII_100MBIT) { printk(": 100 MB Half-Duplex (auto-neg)\n"); } else if (eMiiConfig & MII_FULLDUPLEX) { printk(": 10 MB Full-Duplex (auto-neg)\n"); } else { printk(": 10 MB Half-Duplex (assumed)\n"); } #ifdef PHY_LOOPBACK /* Enable PHY loopback */ mii_loopback(dev); #endif /* Check for FULL/HALF duplex */ if (eMiiConfig & MII_FULLDUPLEX) { pDevCtrl->emac->txControl = EMAC_FD; } }