static int32_t mvl_mii_write(const struct gcu_adapter *adapter, uint32_t mphy, uint32_t phy_num, uint32_t reg_addr, uint16_t phy_data) { int32_t cnt, rc; uint16_t smi_cmd_reg; smi_cmd_reg = gen_mvl_smi_cmd_reg(phy_num, reg_addr, MVL_SMI_WRITE_OP); rc = mii_write(adapter, mphy, MVL_SMI_DATA_REG, phy_data); if (rc < 0) return -1; rc = mii_write(adapter, mphy, MVL_SMI_CMD_REG, smi_cmd_reg); if (rc < 0) return -1; cnt = 0; do { udelay(0x32); rc = mii_read(adapter, mphy, MVL_SMI_CMD_REG, &smi_cmd_reg); if (rc < 0) return -1; if (cnt++ > 10000) return -1; } while ((smi_cmd_reg & (1 << 15))); return 0; }
/* phy_tuning_mse */ void phy_tuning_mse(struct net_device *dev) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); volatile EmacRegisters *emac = pDevCtrl->emac; int phyaddr; int val; int i = 0; int retry = 0; phyaddr = pDevCtrl->EnetInfo.ucPhyAddress; val = mii_read(dev, phyaddr, MII_BRCM_TEST); val |= MII_BRCM_TEST_SHADOW_ENABLE; mii_write(dev, phyaddr, MII_BRCM_TEST, val); // enabled shadow mode do { i++; val = mii_read(dev, phyaddr, MII_AUX_STATUS3); // read the MSE value if ((val & MII_AUX_STATUS3_MSE_MASK) >= 0x4000) { val = mii_read(dev, phyaddr, MII_TX_CONTROL); val &= ~MII_TX_CONTROL_PGA_FIX_ENABLE; mii_write(dev, phyaddr, MII_TX_CONTROL, val); // pga fix disable udelay(100); /* wait ~100usec */ val |= MII_TX_CONTROL_PGA_FIX_ENABLE; mii_write(dev, phyaddr, MII_TX_CONTROL, val); // pga fix enable i = 0; retry++; } if ((i > 12) || (retry > 2)) // read twelve times to ensure good break; } while (1); val = mii_read(dev, phyaddr, MII_BRCM_TEST); val &= ~MII_BRCM_TEST_SHADOW_ENABLE; mii_write(dev, phyaddr, MII_BRCM_TEST, val); // disabled shadow mode }
/* BCM5325E register access through MDC/MDIO */ static void ethsw_mdio_rreg(struct net_device *dev, int page, int reg, uint8 *data, int len) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); volatile EmacRegisters *emac; int cmd, res, ret; int max_retry = 0; emac = pDevCtrl->emac; cmd = (page << REG_PPM_REG16_SWITCH_PAGE_NUMBER_SHIFT) | REG_PPM_REG16_MDIO_ENABLE; mii_write(dev, PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG16, cmd); cmd = (reg << REG_PPM_REG17_REG_NUMBER_SHIFT) | REG_PPM_REG17_OP_READ; mii_write(dev, PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG17, cmd); do { res = mii_read(dev, PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG17); udelay(10); } while ((max_retry++ < 5) && ((res & (REG_PPM_REG17_OP_WRITE|REG_PPM_REG17_OP_READ)) != REG_PPM_REG17_OP_DONE)); ret = 0; ret |= mii_read(dev, PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG24) << 0; ret |= mii_read(dev, PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG25) << 16; switch (len) { case 1: *data = (uint8)ret; break; case 2: *(uint16 *)data = (uint16)ret; break; case 4: *(uint32 *)data = ret; break; } }
void mac_phy_reset(void){ palSetPad(GPIOD, GPIOD_EPHY_NRST); halPolledDelay(BOARD_PHY_HARD_RESET_DELAY); /* PHY soft reset procedure.*/ mii_write(ÐD1, MII_BMCR, BMCR_RESET); while (mii_read(ÐD1, MII_BMCR) & BMCR_RESET) ; mii_write(ÐD1, PHYCTRL2, mii_read(ÐD1, PHYCTRL2) | RMII_RCLKSEL); }
void mii_switch_unPort_vlan_base_mode(struct net_device *dev) { uint16 v16; uint8 i=0; BcmEnet_devctrl* pDevCtrl = NULL; /*add of support ADM6996M LSW by l39225 20061218*/ if(dev == NULL) { printk(" dev is NULL\n"); return; } pDevCtrl= netdev_priv(dev); if(pDevCtrl == NULL) { printk(" pDevCtrl is NULL\n"); return; } if ( ESW_TYPE_ADM6996M == pDevCtrl->ethSwitch.type) { int val; val = 0x2f; for (i =0;i<4;i++) { mii_write(dev, 0, SWI_VLANFILTER_LOWREG0 +2*i , val); } val = 0x30; mii_write(dev, 0, SWI_VLANFILTER_LOWREG0 +2*4 , val); val = 0x3f; mii_write(dev, 0, SWI_VLANFILTER_LOWREG0 +2*5 , val); } /*end of support ADM6996M LSW by l39225 20061218*/ else { v16 = 0xffff; for (i = 0; i < 5 ; i++) { ethsw_wreg(dev, PAGE_PORT_VLAN, 2*i, &v16, sizeof(v16)); } v16 = 0xffff; ethsw_wreg(dev, PAGE_PORT_VLAN, 0x10, &v16, sizeof(v16)); } }
static void mii_init(au1x00_emac_softc_t *sc) { uint16_t data; mii_write(sc, 0, 0x8000); /* reset */ do { mii_read(sc, 0, &data); } while (data & 0x8000); mii_write(sc, 0, 0x3200); /* reset autonegotiation */ mii_write(sc, 17, 0xffc0); /* setup LEDs */ }
static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) { int phy_addr; struct netdev_private *np = netdev_priv(dev); struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru; phy_addr = np->phy_addr; switch (cmd) { case SIOCDEVPRIVATE: break; case SIOCGMIIPHY: miidata->phy_id = phy_addr; break; case SIOCGMIIREG: miidata->val_out = mii_read (dev, phy_addr, miidata->reg_num); break; case SIOCSMIIREG: if (!capable(CAP_NET_ADMIN)) return -EPERM; mii_write (dev, phy_addr, miidata->reg_num, miidata->val_in); break; default: return -EOPNOTSUPP; } return 0; }
void ethmac_start(const uint8_t* address) { // Copy MAC address int i; for (i = 0; i < 6; i++) { mac.mac_address[i] = address[i]; } /* MAC clocks activation and commanded reset procedure.*/ *ethmac_get_DMABMR() |= ETHMAC_DMABMR__SR; while (*ethmac_get_DMABMR() & ETHMAC_DMABMR__SR) ; // Reset the descriptors ethmac_descriptors_reset(); /* ISR vector enabled.*/ nvic_enable_interrupt_line(NVIC_IRQ_LINE_ETH); /* PHY in power up mode.*/ mii_write(MII_BMCR, mii_read(MII_BMCR) & ~MII_BMCR__PDOWN); /* MAC configuration.*/ *ethmac_get_MACFFR() = 0; *ethmac_get_MACFCR() = 0; *ethmac_get_MACVLANTR() = 0; /* MAC address setup.*/ set_mac_address(mac.mac_address); /* Transmitter and receiver enabled. Note that the complete setup of the MAC is performed when the link status is detected.*/ // No checksum offload *ethmac_get_MACCR() = ETHMAC_MACCR__RE | ETHMAC_MACCR__TE; /* DMA configuration: Descriptor chains pointers.*/ *ethmac_get_DMARDLAR() = (uint32_t) ethmac_rx_des; *ethmac_get_DMATDLAR() = (uint32_t) ethmac_tx_des; /* Enabling required interrupt sources.*/ *ethmac_get_DMASR() = (uint32_t) (*ethmac_get_DMASR()); *ethmac_get_DMAIER() = ETHMAC_DMAIER__NISE | ETHMAC_DMAIER__AISE | ETHMAC_DMAIER__RIE | ETHMAC_DMAIER__TIE; /* DMA general settings.*/ *ethmac_get_DMABMR() = ETHMAC_DMABMR__AAB | ETHMAC_DMABMR__RDP_1Beat | ETHMAC_DMABMR__PBL_1Beat; /* Transmit FIFO flush.*/ *ethmac_get_DMAOMR() = ETHMAC_DMAOMR__FTF; while (*ethmac_get_DMAOMR() & ETHMAC_DMAOMR__FTF) ; /* DMA final configuration and start.*/ *ethmac_get_DMAOMR() = ETHMAC_DMAOMR__DTCEFD | ETHMAC_DMAOMR__RSF | ETHMAC_DMAOMR__TSF | ETHMAC_DMAOMR__ST | ETHMAC_DMAOMR__SR; }
/** * Check link status * * @v smsc95xx SMSC95xx device * @ret rc Return status code */ static int smsc95xx_check_link ( struct smsc95xx_device *smsc95xx ) { struct net_device *netdev = smsc95xx->netdev; int intr; int rc; /* Read PHY interrupt source */ intr = mii_read ( &smsc95xx->mii, SMSC95XX_MII_PHY_INTR_SOURCE ); if ( intr < 0 ) { rc = intr; DBGC ( smsc95xx, "SMSC95XX %p could not get PHY interrupt " "source: %s\n", smsc95xx, strerror ( rc ) ); return rc; } /* Acknowledge PHY interrupt */ if ( ( rc = mii_write ( &smsc95xx->mii, SMSC95XX_MII_PHY_INTR_SOURCE, intr ) ) != 0 ) { DBGC ( smsc95xx, "SMSC95XX %p could not acknowledge PHY " "interrupt: %s\n", smsc95xx, strerror ( rc ) ); return rc; } /* Check link status */ if ( ( rc = mii_check_link ( &smsc95xx->mii, netdev ) ) != 0 ) { DBGC ( smsc95xx, "SMSC95XX %p could not check link: %s\n", smsc95xx, strerror ( rc ) ); return rc; } DBGC ( smsc95xx, "SMSC95XX %p link %s (intr %#04x)\n", smsc95xx, ( netdev_link_ok ( netdev ) ? "up" : "down" ), intr ); return 0; }
int mii_init(struct net_device *dev) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); volatile EmacRegisters *emac; int data32; char *phytype = ""; char *setup = ""; switch(pDevCtrl->EnetInfo.ucPhyType) { case BP_ENET_INTERNAL_PHY: phytype = "Internal PHY"; break; case BP_ENET_EXTERNAL_PHY: phytype = "External PHY"; break; default: printk(KERN_INFO ": Unknown PHY type\n"); return -1; } switch (pDevCtrl->EnetInfo.usConfigType) { case BP_ENET_CONFIG_MDIO: setup = "MDIO"; break; default: setup = "Undefined Interface"; break; } printk(KERN_INFO "Config %s Through %s", phytype, setup); emac = pDevCtrl->emac; switch(pDevCtrl->EnetInfo.ucPhyType) { case BP_ENET_INTERNAL_PHY: /* init mii clock, do soft reset of phy, default is 10Base-T */ emac->mdioFreq = EMAC_MII_PRE_EN | EMAC_MDC; /* reset phy */ mii_soft_reset(dev, pDevCtrl->EnetInfo.ucPhyAddress); mii_setup(dev); break; case BP_ENET_EXTERNAL_PHY: emac->config |= EMAC_EXT_PHY; emac->mdioFreq = EMAC_MII_PRE_EN | EMAC_MDC; /* reset phy */ mii_soft_reset(dev, pDevCtrl->EnetInfo.ucPhyAddress); data32 = mii_read(dev, pDevCtrl->EnetInfo.ucPhyAddress, MII_ADVERTISE); data32 |= ADVERTISE_FDFC; /* advertise flow control capbility */ mii_write(dev, pDevCtrl->EnetInfo.ucPhyAddress, MII_ADVERTISE, data32); mii_setup(dev); break; default: break; } return 0; }
/* 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; }
/** * Reset MII interface * * @v mii MII interface * @ret rc Return status code */ int mii_reset ( struct mii_interface *mii ) { unsigned int i; int bmcr; int rc; /* Power-up, enable autonegotiation and initiate reset */ if ( ( rc = mii_write ( mii, MII_BMCR, ( BMCR_RESET | BMCR_ANENABLE ) ) ) != 0 ) { DBGC ( mii, "MII %p could not write BMCR: %s\n", mii, strerror ( rc ) ); return rc; } /* Wait for reset to complete */ for ( i = 0 ; i < MII_RESET_MAX_WAIT_MS ; i++ ) { /* Check if reset has completed */ bmcr = mii_read ( mii, MII_BMCR ); if ( bmcr < 0 ) { rc = bmcr; DBGC ( mii, "MII %p could not read BMCR: %s\n", mii, strerror ( rc ) ); return rc; } /* If reset is not complete, delay 1ms and retry */ if ( bmcr & BMCR_RESET ) { mdelay ( 1 ); continue; } /* Force autonegotation on again, in case it was * cleared by the reset. */ if ( ( rc = mii_write ( mii, MII_BMCR, BMCR_ANENABLE ) ) != 0 ){ DBGC ( mii, "MII %p could not write BMCR: %s\n", mii, strerror ( rc ) ); return rc; } DBGC ( mii, "MII %p reset after %dms\n", mii, i ); return 0; } DBGC ( mii, "MII %p timed out waiting for reset\n", mii ); return -ETIMEDOUT; }
/* reset the MII */ static void mii_soft_reset(struct net_device *dev, int PhyAddr) { int val; mii_write(dev, PhyAddr, MII_BMCR, BMCR_RESET); udelay(10); /* wait ~10usec */ do { val = mii_read(dev, PhyAddr, MII_BMCR); } while (val & BMCR_RESET); }
void mii_dealan(struct local *l, unsigned timo) { unsigned anar, bound; anar = ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA; mii_write(l, l->phy, MII_ANAR, anar); mii_write(l, l->phy, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); l->anlpar = 0; bound = getsecs() + timo; do { l->bmsr = mii_read(l, l->phy, MII_BMSR) | mii_read(l, l->phy, MII_BMSR); /* read twice */ if ((l->bmsr & BMSR_LINK) && (l->bmsr & BMSR_ACOMP)) { l->anlpar = mii_read(l, l->phy, MII_ANLPAR); break; } DELAY(10 * 1000); } while (getsecs() < bound); return; }
static void pga_fix_enable(struct net_device *dev) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); int val; int phyaddr; phyaddr = pDevCtrl->EnetInfo.ucPhyAddress; val = (MII_BRCM_TEST_HARDRESET | MII_BRCM_TEST_10BT_SERIAL_NODRIB | MII_BRCM_TEST_100TX_POWERDOWN | MII_BRCM_TEST_10BT_POWERDOWN ); mii_write(dev, phyaddr, MII_BRCM_TEST, val); // reset phy val = mii_read(dev, phyaddr, MII_BRCM_TEST); val |= MII_BRCM_TEST_SHADOW_ENABLE; mii_write(dev, phyaddr, MII_BRCM_TEST, val); // shadow mode val = mii_read(dev, phyaddr, MII_TX_CONTROL); val |= MII_TX_CONTROL_PGA_FIX_ENABLE; mii_write(dev, phyaddr, MII_TX_CONTROL, val); // pga fix enable val = mii_read(dev, phyaddr, MII_BRCM_TEST); val &= ~MII_BRCM_TEST_SHADOW_ENABLE; mii_write(dev, phyaddr, MII_BRCM_TEST, val); // shadow mode }
static void vt_enable_port(int phy) { const struct gcu_adapter *adapter; adapter = gcu_get_adapter(); if (!adapter) { printk("No adapter??\n"); return; } mii_write(adapter, phy, 23, 0x1100); gcu_release_adapter(&adapter); }
/* set the MII loopback mode */ static void mii_loopback(struct net_device *dev) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); uint32 val; TRACE(("mii_loopback\n")); val = mii_read(dev, pDevCtrl->EnetInfo.ucPhyAddress, MII_BMCR); /* Disable autonegotiation */ val &= ~BMCR_ANENABLE; /* Enable Loopback */ val |= BMCR_LOOPBACK; mii_write(dev, pDevCtrl->EnetInfo.ucPhyAddress, MII_BMCR, val); }
static int mii_set_media_pcs (struct net_device *dev) { __u16 bmcr; __u16 esr; __u16 anar; int phy_addr; struct netdev_private *np; np = netdev_priv(dev); phy_addr = np->phy_addr; /* Auto-Negotiation? */ if (np->an_enable) { /* Advertise capabilities */ esr = mii_read (dev, phy_addr, PCS_ESR); anar = mii_read (dev, phy_addr, MII_ANAR) & ~PCS_ANAR_HALF_DUPLEX & ~PCS_ANAR_FULL_DUPLEX; if (esr & (MII_ESR_1000BT_HD | MII_ESR_1000BX_HD)) anar |= PCS_ANAR_HALF_DUPLEX; if (esr & (MII_ESR_1000BT_FD | MII_ESR_1000BX_FD)) anar |= PCS_ANAR_FULL_DUPLEX; anar |= PCS_ANAR_PAUSE | PCS_ANAR_ASYMMETRIC; mii_write (dev, phy_addr, MII_ANAR, anar); /* Soft reset PHY */ mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET); bmcr = MII_BMCR_AN_ENABLE | MII_BMCR_RESTART_AN | MII_BMCR_RESET; mii_write (dev, phy_addr, MII_BMCR, bmcr); mdelay(1); } else { /* Force speed setting */ /* PHY Reset */ bmcr = MII_BMCR_RESET; mii_write (dev, phy_addr, MII_BMCR, bmcr); mdelay(10); if (np->full_duplex) { bmcr = MII_BMCR_DUPLEX_MODE; printk (KERN_INFO "Manual full duplex\n"); } else { bmcr = 0; printk (KERN_INFO "Manual half duplex\n"); } mii_write (dev, phy_addr, MII_BMCR, bmcr); mdelay(10); /* Advertise nothing */ mii_write (dev, phy_addr, MII_ANAR, 0); } return 0; }
void mii_switch_unmanage_mode(struct net_device *dev) { uint8 value; BcmEnet_devctrl* pDevCtrl = NULL; /*add of support ADM6996M LSW by l39225 20061218*/ if(dev == NULL) { printk(" dev is NULL\n"); return; } pDevCtrl= netdev_priv(dev); if(pDevCtrl == NULL) { printk(" pDevCtrl is NULL\n"); return; } if ( ESW_TYPE_ADM6996M == pDevCtrl->ethSwitch.type) { int val; val = mii_read(dev,0,SWI_SYSTEM_CTRLREG3); val &= ~0x1800; mii_write(dev, 0, SWI_SYSTEM_CTRLREG3, val); } /*end of support ADM6996M LSW by l39225 20061218*/ else { ethsw_rreg(dev, PAGE_CONTROL, REG_SWITCH_MODE, &value, sizeof(value)); value &= ~REG_SWITCH_MODE_FRAME_MANAGE_MODE; ethsw_wreg(dev, PAGE_CONTROL, REG_SWITCH_MODE, &value, sizeof(value)); value = 0; ethsw_wreg(dev, PAGE_MANAGEMENT, REG_GLOBAL_CONFIG, &value, sizeof(value)); } }
void ethmac_enable() { // Enable the clocks rcc_ahb_enable(RCC_AHB_BIT_ETHMAC); rcc_ahb_enable(RCC_AHB_BIT_ETHMACTX); rcc_ahb_enable(RCC_AHB_BIT_ETHMACRX); // Configure MII uint32_t tmp = *ethmac_get_MACMIIAR(); tmp &= ~ETHMAC_MACMIIAR__CR_MASK; tmp |= mac.mii_cr; *ethmac_get_MACMIIAR() = tmp; // Find the PHY address mii_find_phy_addr(); // Reset the PHY log_debug("Resetting PHY... (was %04x)", mii_read(MII_BMCR)); mii_write(MII_BMCR, MII_BMCR__RESET); while (mii_read(MII_BMCR) & MII_BMCR__RESET) ; log_debug("\tOK (now %04x)", mii_read(MII_BMCR)); }
static void ethsw_mdio_wreg(struct net_device *dev, int page, int reg, uint8 *data, int len) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); volatile EmacRegisters *emac; uint32 cmd, res; int val = 0; int max_retry = 0; emac = pDevCtrl->emac; switch (len) { case 1: val = *data; break; case 2: val = *(uint16 *)data; break; case 4: val = *(uint32 *)data; break; } cmd = (page << REG_PPM_REG16_SWITCH_PAGE_NUMBER_SHIFT) | REG_PPM_REG16_MDIO_ENABLE; mii_write(dev, PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG16, cmd); cmd = val>>0 & 0xffff; mii_write(dev, PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG24, cmd); cmd = val>>16 & 0xffff; mii_write(dev, PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG25, cmd); cmd = 0; mii_write(dev, PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG26, cmd); cmd = 0; mii_write(dev, PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG27, cmd); cmd = (reg << REG_PPM_REG17_REG_NUMBER_SHIFT) | REG_PPM_REG17_OP_WRITE; mii_write(dev, PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG17, cmd); do { res = mii_read(dev, PSEUDO_PHY_ADDR, REG_PSEUDO_PHY_MII_REG17); udelay(10); } while ((max_retry++ < 5) && ((res & (REG_PPM_REG17_OP_WRITE|REG_PPM_REG17_OP_READ)) != REG_PPM_REG17_OP_DONE)); }
static int mii_set_media (struct net_device *dev) { __u16 pscr; __u16 bmcr; __u16 bmsr; __u16 anar; int phy_addr; struct netdev_private *np; np = netdev_priv(dev); phy_addr = np->phy_addr; /* Does user set speed? */ if (np->an_enable) { /* Advertise capabilities */ bmsr = mii_read (dev, phy_addr, MII_BMSR); anar = mii_read (dev, phy_addr, MII_ANAR) & ~MII_ANAR_100BX_FD & ~MII_ANAR_100BX_HD & ~MII_ANAR_100BT4 & ~MII_ANAR_10BT_FD & ~MII_ANAR_10BT_HD; if (bmsr & MII_BMSR_100BX_FD) anar |= MII_ANAR_100BX_FD; if (bmsr & MII_BMSR_100BX_HD) anar |= MII_ANAR_100BX_HD; if (bmsr & MII_BMSR_100BT4) anar |= MII_ANAR_100BT4; if (bmsr & MII_BMSR_10BT_FD) anar |= MII_ANAR_10BT_FD; if (bmsr & MII_BMSR_10BT_HD) anar |= MII_ANAR_10BT_HD; anar |= MII_ANAR_PAUSE | MII_ANAR_ASYMMETRIC; mii_write (dev, phy_addr, MII_ANAR, anar); /* Enable Auto crossover */ pscr = mii_read (dev, phy_addr, MII_PHY_SCR); pscr |= 3 << 5; /* 11'b */ mii_write (dev, phy_addr, MII_PHY_SCR, pscr); /* Soft reset PHY */ mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET); bmcr = MII_BMCR_AN_ENABLE | MII_BMCR_RESTART_AN | MII_BMCR_RESET; mii_write (dev, phy_addr, MII_BMCR, bmcr); mdelay(1); } else { /* Force speed setting */ /* 1) Disable Auto crossover */ pscr = mii_read (dev, phy_addr, MII_PHY_SCR); pscr &= ~(3 << 5); mii_write (dev, phy_addr, MII_PHY_SCR, pscr); /* 2) PHY Reset */ bmcr = mii_read (dev, phy_addr, MII_BMCR); bmcr |= MII_BMCR_RESET; mii_write (dev, phy_addr, MII_BMCR, bmcr); /* 3) Power Down */ bmcr = 0x1940; /* must be 0x1940 */ mii_write (dev, phy_addr, MII_BMCR, bmcr); mdelay (100); /* wait a certain time */ /* 4) Advertise nothing */ mii_write (dev, phy_addr, MII_ANAR, 0); /* 5) Set media and Power Up */ bmcr = MII_BMCR_POWER_DOWN; if (np->speed == 100) { bmcr |= MII_BMCR_SPEED_100; printk (KERN_INFO "Manual 100 Mbps, "); } else if (np->speed == 10) { printk (KERN_INFO "Manual 10 Mbps, "); } if (np->full_duplex) { bmcr |= MII_BMCR_DUPLEX_MODE; printk (KERN_CONT "Full duplex\n"); } else { printk (KERN_CONT "Half duplex\n"); } #if 0 /* Set 1000BaseT Master/Slave setting */ mscr = mii_read (dev, phy_addr, MII_MSCR); mscr |= MII_MSCR_CFG_ENABLE; mscr &= ~MII_MSCR_CFG_VALUE = 0; #endif mii_write (dev, phy_addr, MII_BMCR, bmcr); mdelay(10); } return 0; }
void mii_switch_frame_manage_mode(struct net_device *dev) { uint8 value; BcmEnet_devctrl* pDevCtrl = NULL; int i = 0; /*add of support ADM6996M LSW by l39225 20061218*/ if(dev == NULL) { printk(" dev is NULL\n"); return; } pDevCtrl= netdev_priv(dev); if(pDevCtrl == NULL) { printk(" pDevCtrl is NULL\n"); return; } if ( ESW_TYPE_ADM6996M == pDevCtrl->ethSwitch.type) { int val; val = mii_read(dev,0,SWI_SYSTEM_CTRLREG3); val |= 0xe000; val &= 0xafff; val |= 0x1800; mii_write(dev, 0, SWI_SYSTEM_CTRLREG3, val); #if 0 //VALN TAG val = mii_read(dev,0,SWI_ARP_CTRLREG ); val |=0x40; mii_write(dev, 0, SWI_ARP_CTRLREG , val); #endif val = BRCM_TYPE; mii_write(dev, 0, SWI_ADMTAG_ETHTYPE , val); val = 0x1ff; mii_write(dev, 0, SWI_SPCTAG_INSCTRL , val); val = 0x2f; for (i =0;i<4;i++) { mii_write(dev, 0, SWI_VLANFILTER_LOWREG0 +2*i , val); } val = 0x30; mii_write(dev, 0, SWI_VLANFILTER_LOWREG0 +2*4 , val); val = 0x3f; mii_write(dev, 0, SWI_VLANFILTER_LOWREG0 +2*5 , val); } /*end of support ADM6996M LSW by l39225 20061218*/ else { ethsw_rreg(dev, PAGE_CONTROL, REG_SWITCH_MODE, &value, sizeof(value)); value |= REG_SWITCH_MODE_FRAME_MANAGE_MODE; value |= REG_SWITCH_MODE_SW_FWDG_EN; ethsw_wreg(dev, PAGE_CONTROL, REG_SWITCH_MODE, &value, sizeof(value)); ethsw_rreg(dev, PAGE_CONTROL, REG_MII_PORT_CONTROL, &value, sizeof(value)); value |= REG_MII_PORT_CONTROL_RX_UCST_EN; value |= REG_MII_PORT_CONTROL_RX_MCST_EN; value |= REG_MII_PORT_CONTROL_RX_BCST_EN; ethsw_wreg(dev, PAGE_CONTROL, REG_MII_PORT_CONTROL, &value, sizeof(value)); value = 0x80; ethsw_wreg(dev, PAGE_MANAGEMENT, REG_GLOBAL_CONFIG, &value, sizeof(value)); ethsw_rreg(dev, PAGE_VLAN, REG_VLAN_CTRL5, &value, sizeof(value)); value |= REG_VLAN_CTRL5_ENBL_MANAGE_RX_BYPASS; value |= REG_VLAN_CTRL5_ENBL_CRC_GEN; ethsw_wreg(dev, PAGE_VLAN, REG_VLAN_CTRL5, &value, sizeof(value)); /* start of y42304 20060809: 使能lanswitch接收BPDU报文 */ ethsw_rreg(dev, PAGE_MANAGEMENT, REG_GLOBAL_CONFIG, &value, sizeof(value)); //value |= 0x82; value |= 0x8a; ethsw_wreg(dev, PAGE_MANAGEMENT, REG_GLOBAL_CONFIG, &value, sizeof(value)); /* end of y42304 20060809: 使能lanswitch接收BPDU报文 */ } }
int mii_init(struct net_device *dev) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); volatile uniMacRegs *umac; volatile rbufRegs * txrx_ctrl; int data32, advertise; printk(KERN_INFO "Config %s Through MDIO\n", gsPhyType[pDevCtrl->EnetInfo.PhyType] ); umac = pDevCtrl->umac; txrx_ctrl = pDevCtrl->txrx_ctrl; switch(pDevCtrl->EnetInfo.PhyType) { case BP_ENET_INTERNAL_PHY: case BP_ENET_EXTERNAL_PHY: /* do we need to set mii clock? do soft reset of phy, default is 10Base-T */ /* reset phy */ mii_soft_reset(dev, pDevCtrl->EnetInfo.PhyAddress); mii_setup(dev); break; case BP_ENET_EXTERNAL_GPHY: txrx_ctrl->rgmii_oob_ctrl |= RGMII_MODE_EN; txrx_ctrl->rgmii_oob_ctrl |= (1 << 16); /* Don't shift tx clock by 90 degree */ /* Find out if the external PHY is really GPHY, advertise 1000 ability if it is*/ data32 = mii_read(dev, pDevCtrl->EnetInfo.PhyAddress, MII_BMSR); if (data32 & BMSR_ERCAP) { data32 = mii_read(dev, pDevCtrl->EnetInfo.PhyAddress, MII_ESTATUS); advertise = mii_read(dev, pDevCtrl->EnetInfo.PhyAddress, MII_CTRL1000); if (data32 & ESTATUS_1000_TFULL) advertise |= ADVERTISE_1000FULL; else if (data32 & ESTATUS_1000_THALF) advertise |= ADVERTISE_1000HALF; mii_write(dev, pDevCtrl->EnetInfo.PhyAddress, MII_CTRL1000, advertise); } mii_setup(dev); break; case BP_ENET_EXTERNAL_GPHY_IBS: txrx_ctrl->rgmii_oob_ctrl |= RGMII_MODE_EN; txrx_ctrl->rgmii_oob_ctrl |= (1 << 16); /* Use in-band signaling for auto config.*/ txrx_ctrl->rgmii_oob_ctrl |= OOB_DISABLE; umac->cmd |= CMD_AUTO_CONFIG; /* Advertise 1000Base capability, neccesary?*/ data32 = mii_read(dev, pDevCtrl->EnetInfo.PhyAddress, MII_BMSR); if (data32 & BMSR_ERCAP) { data32 = mii_read(dev, pDevCtrl->EnetInfo.PhyAddress, MII_ESTATUS); advertise = mii_read(dev, pDevCtrl->EnetInfo.PhyAddress, MII_CTRL1000); if (data32 & ESTATUS_1000_TFULL) advertise |= ADVERTISE_1000FULL; else if (data32 & ESTATUS_1000_THALF) advertise |= ADVERTISE_1000HALF; mii_write(dev, pDevCtrl->EnetInfo.PhyAddress, MII_CTRL1000, advertise); } mii_setup(dev); break; case BP_ENET_EXTERNAL_MOCA: umac->cmd = umac->cmd | (UMAC_SPEED_1000 << CMD_SPEED_SHIFT); break; default: break; } return 0; }
/*start of add lsw port separate by port_base vlan by 139225 2006-8-15*/ void mii_switch_port_vlan_base_mode(struct net_device *dev,unsigned short vlan) { uint16 v16; uint8 i = 0; uint8 j = 0; uint8 uPort[5] ={0,0,0,0,0}; int val = 0; BcmEnet_devctrl* pDevCtrl = NULL; /*add of support ADM6996M LSW by l39225 20061218*/ if(dev == NULL) { printk(" dev is NULL\n"); return; } pDevCtrl= netdev_priv(dev); if(pDevCtrl == NULL) { printk(" pDevCtrl is NULL\n"); return; } for ( i= 0; i < 5; i++) { if( ((vlan >> i ) & 0x0001) > 0) { uPort[i] = 1; } } if ( ESW_TYPE_ADM6996M != pDevCtrl->ethSwitch.type) { for(i = 0; i < 5;i++) { for (j= i+1; j < 5; j++) { if ( (uPort[i] > 0) && (uPort[j] > 0) ) { ethsw_rreg(dev, PAGE_PORT_VLAN, i*2, &v16, sizeof(v16)); v16 |= 0x0100; //forward only to MII port v16 |= (0x0001 << j); ethsw_wreg(dev, PAGE_PORT_VLAN, i*2, &v16, sizeof(v16)); ethsw_rreg(dev, PAGE_PORT_VLAN, 2*j, &v16, sizeof(v16)); v16 |= 0x0100; v16 |= (0x0001 << i); ethsw_wreg(dev, PAGE_PORT_VLAN, 2*j, &v16, sizeof(v16)); } else if( (uPort[i] == 0) && (uPort[j] == 0)) { continue; } else { ethsw_rreg(dev, PAGE_PORT_VLAN, i*2, &v16, sizeof(v16)); v16 |= 0x0100; //forward only to MII port v16 &= ~(0x0001 << j); ethsw_wreg(dev, PAGE_PORT_VLAN, i*2, &v16, sizeof(v16)); ethsw_rreg(dev, PAGE_PORT_VLAN, 2*j, &v16, sizeof(v16)); v16 |= 0x0100; v16 &= ~(0x0001 << i); ethsw_wreg(dev, PAGE_PORT_VLAN, 2*j, &v16, sizeof(v16)); } } } v16 = 0xffff; ethsw_wreg(dev, PAGE_PORT_VLAN , 0x10, &v16, sizeof(v16)); } else { for(i = 0; i < 5;i++) { for (j= i+1; j < 5; j++) { if ( (uPort[i] > 0) && (uPort[j] > 0) ) { val = mii_read(dev,0,SWI_VLANFILTER_LOWREG0 +2*i); val |= 0x20; //forward only to MII port val |= (0x0001 << j); mii_write(dev, 0, SWI_VLANFILTER_LOWREG0 +2*i , val); val = mii_read(dev,0,SWI_VLANFILTER_LOWREG0 +2*j); val |= 0x20; //forward only to MII port val |= (0x0001 << i); mii_write(dev, 0, SWI_VLANFILTER_LOWREG0 +2*j , val); } else if( (uPort[i] == 0) && (uPort[j] == 0)) { continue; } else { val = mii_read(dev,0,SWI_VLANFILTER_LOWREG0 +2*i); val |= 0x020; //forward only to MII port val &= ~(0x0001 << j); mii_write(dev, 0, SWI_VLANFILTER_LOWREG0 +2*i , val); val = mii_read(dev,0,SWI_VLANFILTER_LOWREG0 +2*j); val |= 0x20; val &= ~(0x0001 << i); mii_write(dev, 0, SWI_VLANFILTER_LOWREG0 +2*j , val); } } } val = 0x3f; mii_write(dev, 0, SWI_VLANFILTER_LOWREG0 +2*5 , val); } }
/** * Open network device * * @v netdev Network device * @ret rc Return status code */ static int smsc95xx_open ( struct net_device *netdev ) { struct smsc95xx_device *smsc95xx = netdev->priv; union smsc95xx_mac mac; int rc; /* Clear stored interrupt status */ smsc95xx->int_sts = 0; /* Copy MAC address */ memset ( &mac, 0, sizeof ( mac ) ); memcpy ( mac.raw, netdev->ll_addr, ETH_ALEN ); /* Configure bulk IN empty response */ if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_HW_CFG, SMSC95XX_HW_CFG_BIR ) ) != 0 ) goto err_hw_cfg; /* Open USB network device */ if ( ( rc = usbnet_open ( &smsc95xx->usbnet ) ) != 0 ) { DBGC ( smsc95xx, "SMSC95XX %p could not open: %s\n", smsc95xx, strerror ( rc ) ); goto err_open; } /* Configure interrupt endpoint */ if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_INT_EP_CTL, ( SMSC95XX_INT_EP_CTL_RXDF_EN | SMSC95XX_INT_EP_CTL_PHY_EN ) ) ) != 0 ) goto err_int_ep_ctl; /* Configure bulk IN delay */ if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_BULK_IN_DLY, SMSC95XX_BULK_IN_DLY_SET ( 0 ) ) ) != 0 ) goto err_bulk_in_dly; /* Configure MAC */ if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_MAC_CR, ( SMSC95XX_MAC_CR_RXALL | SMSC95XX_MAC_CR_FDPX | SMSC95XX_MAC_CR_MCPAS | SMSC95XX_MAC_CR_PRMS | SMSC95XX_MAC_CR_PASSBAD | SMSC95XX_MAC_CR_TXEN | SMSC95XX_MAC_CR_RXEN ) ) ) != 0 ) goto err_mac_cr; /* Configure transmit datapath */ if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_TX_CFG, SMSC95XX_TX_CFG_ON ) ) != 0 ) goto err_tx_cfg; /* Write MAC address high register */ if ( ( rc = smsc95xx_raw_writel ( smsc95xx, SMSC95XX_ADDRH, mac.addr.h ) ) != 0 ) goto err_addrh; /* Write MAC address low register */ if ( ( rc = smsc95xx_raw_writel ( smsc95xx, SMSC95XX_ADDRL, mac.addr.l ) ) != 0 ) goto err_addrl; /* Enable PHY interrupts */ if ( ( rc = mii_write ( &smsc95xx->mii, SMSC95XX_MII_PHY_INTR_MASK, ( SMSC95XX_PHY_INTR_ANEG_DONE | SMSC95XX_PHY_INTR_LINK_DOWN ) ) ) != 0 ) { DBGC ( smsc95xx, "SMSC95XX %p could not set PHY interrupt " "mask: %s\n", smsc95xx, strerror ( rc ) ); goto err_phy_intr_mask; } /* Update link status */ smsc95xx_check_link ( smsc95xx ); return 0; err_phy_intr_mask: err_addrl: err_addrh: err_tx_cfg: err_mac_cr: err_bulk_in_dly: err_int_ep_ctl: usbnet_close ( &smsc95xx->usbnet ); err_open: err_hw_cfg: smsc95xx_reset ( smsc95xx ); return rc; }
void vEMACInit( void ) { int iData; extern int periph_clk_khz; const unsigned portCHAR ucMACAddress[] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 }; /* Enable the ENET clock. */ SIM_SCGC2 |= SIM_SCGC2_ENET_MASK; /* Allow concurrent access to MPU controller to avoid bus errors. */ MPU_CESR = 0; prvInitialiseDescriptors(); /* Reset and enable. */ ENET_ECR = ENET_ECR_RESET_MASK; /* Wait at least 8 clock cycles */ vTaskDelay( 2 ); /* Start the MII interface*/ mii_init( 0, periph_clk_khz / 1000L ); /* Configure the transmit interrupt. */ set_irq_priority( emacTX_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); enable_irq( emacTX_INTERRUPT_NO ); /* Configure the receive interrupt. */ set_irq_priority( emacRX_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); enable_irq( emacRX_INTERRUPT_NO ); /* Configure the error interrupt. */ set_irq_priority( emacERROR_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); enable_irq( emacERROR_INTERRUPT_NO ); /* Configure the pins to the PHY - RMII mode used. */ PORTB_PCR0 = PORT_PCR_MUX( 4 ); /* RMII0_MDIO / MII0_MDIO. */ PORTB_PCR1 = PORT_PCR_MUX( 4 ); /* RMII0_MDC / MII0_MDC */ PORTA_PCR14 = PORT_PCR_MUX( 4 ); /* RMII0_CRS_DV / MII0_RXDV */ PORTA_PCR12 = PORT_PCR_MUX( 4 ); /* RMII0_RXD1 / MII0_RXD1 */ PORTA_PCR13 = PORT_PCR_MUX( 4 ); /* RMII0_RXD0/MII0_RXD0 */ PORTA_PCR15 = PORT_PCR_MUX( 4 ); /* RMII0_TXEN/MII0_TXEN */ PORTA_PCR16 = PORT_PCR_MUX( 4 ); /* RMII0_TXD0/MII0_TXD0 */ PORTA_PCR17 = PORT_PCR_MUX( 4 ); /* RMII0_TXD1/MII0_TXD1 */ /* Is there communication with the PHY? */ do { vTaskDelay( emacLINK_DELAY ); iData = 0xFFFF; mii_read( 0, configPHY_ADDRESS, PHY_PHYIDR1, &iData ); } while( iData == 0xFFFF ); /* Start to auto negotiate. */ mii_write( 0, configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) ); /* Wait for auto negotiate to complete. */ do { vTaskDelay( emacLINK_DELAY ); mii_read( 0, configPHY_ADDRESS, PHY_BMSR, &iData ); } while( !( iData & PHY_BMSR_AN_COMPLETE ) ); /* A link has been established. What was negotiated? */ iData = 0; mii_read( 0, configPHY_ADDRESS, emacPHY_STATUS, &iData ); /* Clear the Individual and Group Address Hash registers */ ENET_IALR = 0; ENET_IAUR = 0; ENET_GALR = 0; ENET_GAUR = 0; /* Set the Physical Address for the selected ENET */ enet_set_address( 0, ucMACAddress ); ENET_RCR = ENET_RCR_MAX_FL( UIP_BUFSIZE ) | ENET_RCR_MII_MODE_MASK | ENET_RCR_CRCFWD_MASK | ENET_RCR_RMII_MODE_MASK; /* Clear the control registers. */ ENET_TCR = 0; if( iData & emacPHY_DUPLEX_STATUS ) { /* Full duplex */ ENET_RCR &= ( unsigned long )~ENET_RCR_DRT_MASK; ENET_TCR |= ENET_TCR_FDEN_MASK; } else { /* Half duplex */ ENET_RCR |= ENET_RCR_DRT_MASK; ENET_TCR &= (unsigned portLONG)~ENET_TCR_FDEN_MASK; } if( iData & emacPHY_SPEED_STATUS ) { /* 10Mbps */ ENET_RCR |= ENET_RCR_RMII_10T_MASK; } ENET_ECR = ENET_ECR_EN1588_MASK; /* Store and forward checksum. */ ENET_TFWR = ENET_TFWR_STRFWD_MASK; /* Set Rx Buffer Size */ ENET_MRBR = ( unsigned short ) UIP_BUFSIZE; /* Point to the start of the circular Rx buffer descriptor queue */ ENET_RDSR = ( unsigned long ) &( xRxDescriptors[ 0 ] ); /* Point to the start of the circular Tx buffer descriptor queue */ ENET_TDSR = ( unsigned long ) &( xTxDescriptors[ 0 ] ); /* Clear all ENET interrupt events */ ENET_EIR = ( unsigned long ) -1; /* Enable interrupts. */ ENET_EIMR = 0 /*rx irqs*/ | ENET_EIMR_RXF_MASK/* only for complete frame, not partial buffer descriptor | ENET_EIMR_RXB_MASK*/ /*xmit irqs*/ | ENET_EIMR_TXF_MASK/* only for complete frame, not partial buffer descriptor | ENET_EIMR_TXB_MASK*/ /*enet irqs*/ | ENET_EIMR_UN_MASK | ENET_EIMR_RL_MASK | ENET_EIMR_LC_MASK | ENET_EIMR_BABT_MASK | ENET_EIMR_BABR_MASK | ENET_EIMR_EBERR_MASK ; /* Enable the MAC itself. */ ENET_ECR |= ENET_ECR_ETHEREN_MASK; /* Indicate that there have been empty receive buffers produced */ ENET_RDAR = ENET_RDAR_RDAR_MASK; }
void mii_enablephyinterrupt(struct net_device *dev, int phy_id) { mii_write(dev, phy_id, MII_INTERRUPT, MII_INTR_ENABLE | MII_INTR_MASK_FDX | MII_INTR_MASK_LINK_SPEED); }
int mii_init(struct net_device *dev) { BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); volatile EmacRegisters *emac; int data32; uint16 data16; #if defined (CONFIG_BCM96338) || defined (CONFIG_BCM96348) uint16 blkEnables; #endif uint8 data8; int i; char *phytype = ""; char *setup = ""; switch(pDevCtrl->EnetInfo.ucPhyType) { case BP_ENET_INTERNAL_PHY: phytype = "Internal PHY"; break; case BP_ENET_EXTERNAL_PHY: phytype = "External PHY"; break; case BP_ENET_EXTERNAL_SWITCH: phytype = "Ethernet Switch"; break; default: printk(KERN_INFO CARDNAME ": Unknown PHY type\n"); return -1; } switch (pDevCtrl->EnetInfo.usConfigType) { case BP_ENET_CONFIG_MDIO_PSEUDO_PHY: setup = "MDIO Pseudo PHY Interface"; break; case BP_ENET_CONFIG_SPI_SSB_0: setup = "SPI Slave Select 0"; break; case BP_ENET_CONFIG_SPI_SSB_1: setup = "SPI Slave Select 1"; break; case BP_ENET_CONFIG_SPI_SSB_2: setup = "SPI Slave Select 2"; break; case BP_ENET_CONFIG_SPI_SSB_3: setup = "SPI Slave Select 3"; break; case BP_ENET_CONFIG_MDIO: setup = "MDIO"; break; /*start of support infineon ADM6996M LSW by l39225 20061218*/ case BP_ENET_CONFIG_SMI: setup = "SMI"; break; /*end of support infineon ADM6996M LSW by l39225 20061218*/ default: setup = "Undefined Interface"; break; } printk("Config %s Through %s\n", phytype, setup); emac = pDevCtrl->emac; switch(pDevCtrl->EnetInfo.ucPhyType) { case BP_ENET_INTERNAL_PHY: /* init mii clock, do soft reset of phy, default is 10Base-T */ emac->mdioFreq = EMAC_MII_PRE_EN | EMAC_MDC; /* reset phy */ mii_soft_reset(dev, pDevCtrl->EnetInfo.ucPhyAddress); #if defined(CONFIG_BCM96338) pga_fix_enable(dev); #endif mii_setup(dev); break; case BP_ENET_EXTERNAL_PHY: emac->config |= EMAC_EXT_PHY; emac->mdioFreq = EMAC_MII_PRE_EN | EMAC_MDC; /* reset phy */ if (pDevCtrl->EnetInfo.usGpioPhyReset != BP_NOT_DEFINED) { data16 = GPIO_NUM_TO_MASK(pDevCtrl->EnetInfo.usGpioPhyReset); GPIO->GPIODir |= data16; if (pDevCtrl->EnetInfo.usGpioPhyReset & BP_ACTIVE_LOW) { GPIO->GPIOio &= ~data16; udelay(400); /* hold > 150us */ GPIO->GPIOio |= data16; } else { GPIO->GPIOio |= data16; udelay(400); /* hold > 150us */ GPIO->GPIOio &= ~data16; } mdelay(1100); /* wait > 1 second */ } else { mii_soft_reset(dev, pDevCtrl->EnetInfo.ucPhyAddress); } data32 = mii_read(dev, pDevCtrl->EnetInfo.ucPhyAddress, MII_ADVERTISE); data32 |= ADVERTISE_FDFC; /* advertise flow control capbility */ mii_write(dev, pDevCtrl->EnetInfo.ucPhyAddress, MII_ADVERTISE, data32); mii_setup(dev); break; case BP_ENET_EXTERNAL_SWITCH: #if defined(CONFIG_BCM96358) GPIO->GPIOMode |= GPIO_MODE_EMAC2_MII_CLK_INV; #endif emac->config |= EMAC_EXT_PHY; emac->mdioFreq = EMAC_MII_PRE_EN | EMAC_MDC; emac->txControl = EMAC_FD; switch (pDevCtrl->EnetInfo.usConfigType) { case BP_ENET_CONFIG_MDIO_PSEUDO_PHY: mii_soft_reset(dev, PSEUDO_PHY_ADDR); break; case BP_ENET_CONFIG_SPI_SSB_0: case BP_ENET_CONFIG_SPI_SSB_1: case BP_ENET_CONFIG_SPI_SSB_2: case BP_ENET_CONFIG_SPI_SSB_3: #if defined (CONFIG_BCM96338) || defined (CONFIG_BCM96348) blkEnables = PERF->blkEnables; if ((blkEnables & SPI_CLK_EN) == 0) { blkEnables |= SPI_CLK_EN; PERF->blkEnables = blkEnables; } pDevCtrl->ethSwitch.cid = 0xff; pDevCtrl->ethSwitch.page = 0xff; #endif break; case BP_ENET_CONFIG_MDIO: /* reset phy */ if (pDevCtrl->EnetInfo.numSwitchPorts) { for (i = 0; i < pDevCtrl->EnetInfo.numSwitchPorts; i++) { mii_soft_reset(dev, pDevCtrl->EnetInfo.ucPhyAddress | i); } } return 0; /*start of support infineon ADM6996M LSW by l39225 20061218*/ case BP_ENET_CONFIG_SMI: if (pDevCtrl->EnetInfo.numSwitchPorts) { for (i = 0; i < pDevCtrl->EnetInfo.numSwitchPorts; i++) { int val; mii_write(dev, 0, SWI_PHYREG_START_ADDR+i*SWI_PHYREG_OFFSET, BMCR_RESET); udelay(10); do { val = mii_read(dev, 0, SWI_PHYREG_START_ADDR+i*SWI_PHYREG_OFFSET); } while (val & BMCR_RESET); } } break; /*end of support infineon ADM6996M LSW by l39225 20061218*/ default: printk(KERN_INFO CARDNAME ": Unknown PHY configuration type\n"); break; } if( pDevCtrl->EnetInfo.usConfigType != BP_ENET_CONFIG_SMI) { if (pDevCtrl->EnetInfo.numSwitchPorts) { data8 = 0; switch (pDevCtrl->EnetInfo.numSwitchPorts) { case 5: data8 |= REG_POWER_DOWN_MODE_PORT5_PHY_DISABLE; case 4: data8 |= REG_POWER_DOWN_MODE_PORT4_PHY_DISABLE; case 3: data8 |= REG_POWER_DOWN_MODE_PORT3_PHY_DISABLE; case 2: data8 |= REG_POWER_DOWN_MODE_PORT2_PHY_DISABLE; case 1: /* * y42304 delete: Do not set bit 0 to a 1 , Doing so * disable pll power and lanswitch function */ //data8 |= REG_POWER_DOWN_MODE_PORT1_PHY_DISABLE; break; default: break; } /* start of enet y42304 modified 20060711: power down port 5*/ data8 |= REG_POWER_DOWN_MODE_PORT5_PHY_DISABLE; /* disable Switch port PHY */ ethsw_wreg(dev, PAGE_CONTROL, REG_POWER_DOWN_MODE, (uint8 *)&data8, sizeof(data8)); /* enable Switch port 0-3 PHY */ data8 |= REG_POWER_DOWN_MODE_PORT1_PHY_DISABLE; data8 = ((~data8) | REG_POWER_DOWN_MODE_PORT5_PHY_DISABLE); ethsw_wreg(dev, PAGE_CONTROL, REG_POWER_DOWN_MODE, (uint8 *)&data8, sizeof(data8)); /* end of enet y42304 modified 20060711: power down port 5*/ } /* setup Switch MII1 port state override */ ethsw_rreg(dev, PAGE_CONTROL, REG_CONTROL_MII1_PORT_STATE_OVERRIDE, &data8, sizeof(data8)); if (pDevCtrl->EnetInfo.usReverseMii == BP_ENET_REVERSE_MII) data8 |= REG_CONTROL_MPSO_REVERSE_MII; data8 |= (REG_CONTROL_MPSO_MII_SW_OVERRIDE|REG_CONTROL_MPSO_LINKPASS); data8 |= (REG_CONTROL_MPSO_LP_FLOW_CONTROL|REG_CONTROL_MPSO_SPEED100|REG_CONTROL_MPSO_FDX); ethsw_wreg(dev, PAGE_CONTROL, REG_CONTROL_MII1_PORT_STATE_OVERRIDE, &data8, sizeof(data8)); /* checking Switch functional */ data8 = 0; ethsw_rreg(dev, PAGE_CONTROL, REG_CONTROL_MII1_PORT_STATE_OVERRIDE, &data8, sizeof(data8)); if ((data8 & (REG_CONTROL_MPSO_MII_SW_OVERRIDE|REG_CONTROL_MPSO_LINKPASS)) != (REG_CONTROL_MPSO_MII_SW_OVERRIDE|REG_CONTROL_MPSO_LINKPASS) || (data8 == 0xff)) { printk(KERN_INFO CARDNAME ": error on Ethernet Switch setup\n"); return -1; } if (pDevCtrl->EnetInfo.usReverseMii == BP_ENET_REVERSE_MII) { if ((data8 & REG_CONTROL_MPSO_REVERSE_MII) != REG_CONTROL_MPSO_REVERSE_MII) { printk(KERN_INFO CARDNAME ": error on Ethernet Switch reverse MII setup\n"); return -1; } } pDevCtrl->ethSwitch.type = ethsw_switch_type(dev); } /*start of support infineon ADM6996M LSW by l39225 20061218*/ else { int i ,v; for( i = 0; i< 5;i++) { v = mii_read(dev,0,0x01+2*i); v |= 0x8000; mii_write(dev,0,0x01+2*i,v); } v = mii_read(dev,0,0x08); v |= 0x8000; mii_write(dev,0,0x08,v); pDevCtrl->ethSwitch.type = ESW_TYPE_ADM6996M; } /*end of support infineon ADM6996M LSW by l39225 20061218*/ break; default: break; } return 0; }
int mii_init(struct net_device *dev) { struct BcmEnet_devctrl *pDevCtrl = netdev_priv(dev); volatile struct uniMacRegs *umac; int bmcr; umac = pDevCtrl->umac; pDevCtrl->mii.phy_id = pDevCtrl->phyAddr; pDevCtrl->mii.phy_id_mask = 0x1f; pDevCtrl->mii.reg_num_mask = 0x1f; pDevCtrl->mii.dev = dev; pDevCtrl->mii.mdio_read = mii_read; pDevCtrl->mii.mdio_write = mii_write; /* Enable autoneg if it's not */ bmcr = mii_read(dev, pDevCtrl->phyAddr, MII_BMCR); switch (pDevCtrl->phyType) { case BRCM_PHY_TYPE_INT: pDevCtrl->mii.supports_gmii = 0; pDevCtrl->sys->sys_port_ctrl = PORT_MODE_INT_EPHY; /* enable APD */ pDevCtrl->ext->ext_pwr_mgmt |= EXT_PWR_DN_EN_LD; pDevCtrl->ext->ext_pwr_mgmt |= EXT_PHY_RESET; udelay(5); pDevCtrl->ext->ext_pwr_mgmt &= ~EXT_PHY_RESET; /* enable 64 clock MDIO */ mii_write(dev, pDevCtrl->phyAddr, 0x1d, 0x1000); mii_read(dev, pDevCtrl->phyAddr, 0x1d); printk(KERN_INFO "Config internal EPHY through MDIO\n"); break; case BRCM_PHY_TYPE_EXT_MII: pDevCtrl->mii.supports_gmii = 0; pDevCtrl->sys->sys_port_ctrl = PORT_MODE_EXT_EPHY; mii_write(dev, pDevCtrl->phyAddr, MII_BMCR, bmcr|MII_BMCR); printk(KERN_INFO "Config EPHY through MDIO\n"); break; case BRCM_PHY_TYPE_EXT_RGMII: GENET_RGMII_OOB_CTRL(pDevCtrl) |= RGMII_MODE_EN; /* Don't shift tx clock by 90 degree, does it still needed? */ GENET_RGMII_OOB_CTRL(pDevCtrl) |= (1 << 16); pDevCtrl->mii.supports_gmii = 1; pDevCtrl->sys->sys_port_ctrl = PORT_MODE_EXT_GPHY; mii_write(dev, pDevCtrl->phyAddr, MII_BMCR, bmcr|MII_BMCR); printk(KERN_INFO "Config GPHY through MDIO\n"); break; case BRCM_PHY_TYPE_EXT_RGMII_IBS: GENET_RGMII_OOB_CTRL(pDevCtrl) |= RGMII_MODE_EN; GENET_RGMII_OOB_CTRL(pDevCtrl) |= (1 << 16); /* Use in-band signaling for auto config.*/ GENET_RGMII_OOB_CTRL(pDevCtrl) |= OOB_DISABLE; umac->cmd |= CMD_AUTO_CONFIG; pDevCtrl->mii.supports_gmii = 1; pDevCtrl->sys->sys_port_ctrl = PORT_MODE_EXT_GPHY; mii_write(dev, pDevCtrl->phyAddr, MII_BMCR, bmcr|MII_BMCR); printk(KERN_INFO "Automatic Config GPHY\n"); break; case BRCM_PHY_TYPE_MOCA: printk(KERN_INFO "Config MoCA...\n"); umac->cmd = umac->cmd | (UMAC_SPEED_1000 << CMD_SPEED_SHIFT); pDevCtrl->mii.force_media = 1; pDevCtrl->sys->sys_port_ctrl = PORT_MODE_INT_GPHY; break; default: printk(KERN_ERR "unknown phy_type : %d\n", pDevCtrl->phyType); break; } return 0; }