/****************************************************************************** * * ip_VLANInit - initialize "port-based VLANs" for the specified enet unit. */ static void ip_VLANInit(int ethUnit) { int phyUnit; uint32_t phyBase; uint32_t phyReg; phyBase = IP_GLOBALREGBASE; for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) { if (IP_ETHUNIT(phyUnit) != ethUnit) { continue; } phy_reg_write(phyBase, IP_GLOBAL_PHY29_ADDR, IP_GLOBAL_PHY29_24_REG + ((phyUnit == 5) ? (phyUnit + 1) : phyUnit), IP_VLAN_TABLE_SETTING(phyUnit)); /* Send all packets to all ports */ phyReg = phy_reg_read(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG); phyReg = phyReg | ((1 << phyUnit) << IP_VLAN1_OUTPUT_PORT_MASK_S); phy_reg_write(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG, phyReg); } phyReg = phy_reg_read(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_9_REG); phyReg = phyReg | TAG_VLAN_ENABLE; phyReg = phyReg & ~VID_INDX_SEL_M; phy_reg_write(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_9_REG, phyReg); }
/****************************************************************************** * * ip_phySetup - reset and setup the PHY switch. * * Resets each PHY port. * * RETURNS: * TRUE --> at least 1 PHY with LINK * FALSE --> no LINKs on this ethernet unit */ BOOL ip_phySetup(int ethUnit) { int phyUnit; UINT16 phyHwStatus; UINT16 timeout; int liveLinks = 0; UINT32 phyBase = 0; BOOL foundPhy = FALSE; UINT32 phyAddr; /* Reset PHYs*/ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) { if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = IP_PHYBASE(phyUnit); phyAddr = IP_PHYADDR(phyUnit); phyRegWrite(phyBase, phyAddr, IP_PHY_CONTROL, IP_CTRL_SOFTWARE_RESET); } /* * After the phy is reset, it takes a little while before * it can respond properly. */ sysMsDelay(300); /* Verify that the switch is what we think it is, and that it's ready */ ip_verifyReady(ethUnit); /* See if there's any configuration data for this enet */ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) { if (IP_ETHUNIT(phyUnit) != ethUnit) { continue; } phyBase = IP_PHYBASE(phyUnit); foundPhy = TRUE; break; } if (!foundPhy) { return FALSE; /* No PHY's configured for this ethUnit */ } #ifdef COBRA_TODO /* Initialize global switch settings */ /* Initialize the aging time */ /* Set the learning properties */ #endif /* start auto negogiation on each phy */ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) { if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = IP_PHYBASE(phyUnit); phyAddr = IP_PHYADDR(phyUnit); phyRegWrite(phyBase, phyAddr, IP_AUTONEG_ADVERT, IP_ADVERTISE_ALL); phyRegWrite(phyBase, phyAddr, IP_PHY_CONTROL, IP_CTRL_AUTONEGOTIATION_ENABLE | IP_CTRL_START_AUTONEGOTIATION); } /* * Wait up to .75 seconds for ALL associated PHYs to finish * autonegotiation. The only way we get out of here sooner is * if ALL PHYs are connected AND finish autonegotiation. */ timeout=5; for (phyUnit=0; (phyUnit < IP_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) { if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } for (;;) { phyBase = IP_PHYBASE(phyUnit); phyAddr = IP_PHYADDR(phyUnit); phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS); if (IP_AUTONEG_DONE(phyHwStatus)) { DRV_PRINT(DRV_DEBUG_PHYSETUP, ("Port %d, Neg Success\n", phyUnit)); break; } if (timeout == 0) { DRV_PRINT(DRV_DEBUG_PHYSETUP, ("Port %d, Negogiation timeout\n", phyUnit)); break; } if (--timeout == 0) { DRV_PRINT(DRV_DEBUG_PHYSETUP, ("Port %d, Negogiation timeout\n", phyUnit)); break; } sysMsDelay(150); } } /* * All PHYs have had adequate time to autonegotiate. * Now initialize software status. * * It's possible that some ports may take a bit longer * to autonegotiate; but we can't wait forever. They'll * get noticed by mv_phyCheckStatusChange during regular * polling activities. */ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) { if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } if (ip_phyIsLinkAlive(phyUnit)) { liveLinks++; IP_IS_PHY_ALIVE(phyUnit) = TRUE; } else { IP_IS_PHY_ALIVE(phyUnit) = FALSE; } DRV_PRINT(DRV_DEBUG_PHYSETUP, ("eth%d: Phy Status=%4.4x\n", ethUnit, phyRegRead(IP_PHYBASE(phyUnit), IP_PHYADDR(phyUnit), IP_PHY_STATUS))); } ip_VLANInit(ethUnit); return (liveLinks > 0); }
/***************************************************************************** * * ip_phyShow - Dump the state of a PHY. * There are two sets of registers for each phy port: * "phy registers" and * "switch port registers" * We dump 'em all, plus the switch global registers. */ void ip_phyShow(int phyUnit) { int i; UINT16 value; UINT32 phyBase; UINT32 phyAddr; if (!ip_validPhyId(phyUnit)) { return; } phyBase = IP_PHYBASE(phyUnit); phyAddr = IP_PHYADDR(phyUnit); printf("PHY state for PHY%d (enet%d, phyBase 0x%8x, phyAddr 0x%x)\n", phyUnit, IP_ETHUNIT(phyUnit), IP_PHYBASE(phyUnit), IP_PHYADDR(phyUnit)); printf("PHY Registers:\n"); for (i=0; i < ipPhyNumRegs; i++) { value = phyRegRead(phyBase, phyAddr, ipPhyRegisterTable[i].regNum); printf("Reg %02d (0x%02x) %s = 0x%08x\n", ipPhyRegisterTable[i].regNum, ipPhyRegisterTable[i].regNum, ipPhyRegisterTable[i].regIdString, value); } phyBase = IP_GLOBALREGBASE; printf("Switch Global Registers:\n"); printf("Phy29 Registers:\n"); for (i=0; i < ipPhy29GlobalNumRegs; i++) { value = phyRegRead(phyBase, IP_GLOBAL_PHY29_ADDR, ipPhy29GlobalRegisterTable[i].regNum); printf("Reg %02d (0x%02x) %s = 0x%08x\n", ipPhy29GlobalRegisterTable[i].regNum, ipPhy29GlobalRegisterTable[i].regNum, ipPhy29GlobalRegisterTable[i].regIdString, value); } printf("Phy30 Registers:\n"); for (i=0; i < ipPhy30GlobalNumRegs; i++) { value = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, ipPhy30GlobalRegisterTable[i].regNum); printf("Reg %02d (0x%02x) %s = 0x%08x\n", ipPhy30GlobalRegisterTable[i].regNum, ipPhy30GlobalRegisterTable[i].regNum, ipPhy30GlobalRegisterTable[i].regIdString, value); } printf("Phy31 Registers:\n"); for (i=0; i < ipPhy31GlobalNumRegs; i++) { value = phyRegRead(phyBase, IP_GLOBAL_PHY31_ADDR, ipPhy31GlobalRegisterTable[i].regNum); printf("Reg %02d (0x%02x) %s = 0x%08x\n", ipPhy31GlobalRegisterTable[i].regNum, ipPhy31GlobalRegisterTable[i].regNum, ipPhy31GlobalRegisterTable[i].regIdString, value); } }
/****************************************************************************** * * ip_VLANInit - initialize "port-based VLANs" for the specified enet unit. */ LOCAL void ip_VLANInit(int ethUnit) { int phyUnit; UINT32 phyBase; UINT32 phyReg; phyBase = IP_GLOBALREGBASE; for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) { if (IP_ETHUNIT(phyUnit) != ethUnit) { continue; } phyRegWrite(phyBase, IP_GLOBAL_PHY29_ADDR, IP_GLOBAL_PHY29_24_REG + ((phyUnit == 5) ? (phyUnit + 1) : phyUnit), IP_VLAN_TABLE_SETTING(phyUnit)); #if CONFIG_VENETDEV if (IP_IS_ENET_PORT(phyUnit)) { if (IP_IS_WAN_PORT(phyUnit)) { /* WAN port */ phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG); phyReg = phyReg & ~((1 << phyUnit) << IP_VLAN1_OUTPUT_PORT_MASK_S); phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG, phyReg); phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_2_REG); phyReg = phyReg | ((1 << phyUnit) << IP_VLAN2_OUTPUT_PORT_MASK_S); phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_2_REG, phyReg); } else { /* LAN ports */ phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG); phyReg = phyReg | ((1 << phyUnit) << IP_VLAN1_OUTPUT_PORT_MASK_S); phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG, phyReg); phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_2_REG); phyReg = phyReg & ~((1 << phyUnit) << IP_VLAN2_OUTPUT_PORT_MASK_S); phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_2_REG, phyReg); } /* WAN & LAN removes VLAN tags */ phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY29_ADDR, IP_GLOBAL_PHY29_23_REG); phyReg = phyReg | ((1 << phyUnit) << IP_PORTX_REMOVE_TAG_S); phyReg = phyReg & ~((1 << phyUnit) << IP_PORTX_ADD_TAG_S); phyRegWrite(phyBase, IP_GLOBAL_PHY29_ADDR, IP_GLOBAL_PHY29_23_REG, phyReg); } else { /* CPU port */ phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG); phyReg = phyReg | ((1 << phyUnit) << IP_VLAN1_OUTPUT_PORT_MASK_S); phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG, phyReg); phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_2_REG); phyReg = phyReg | ((1 << phyUnit) << IP_VLAN2_OUTPUT_PORT_MASK_S); phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_2_REG, phyReg); phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY29_ADDR, IP_GLOBAL_PHY29_23_REG); phyReg = phyReg | (1 << IP_PORT5_ADD_TAG_S); phyReg = phyReg & ~(1 << IP_PORT5_REMOVE_TAG_S); phyRegWrite(phyBase, IP_GLOBAL_PHY29_ADDR, IP_GLOBAL_PHY29_23_REG, phyReg); } #else /* Send all packets to all ports */ phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG); phyReg = phyReg | ((1 << phyUnit) << IP_VLAN1_OUTPUT_PORT_MASK_S); phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG, phyReg); #endif } phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_9_REG); phyReg = phyReg | TAG_VLAN_ENABLE; phyReg = phyReg & ~VID_INDX_SEL_M; phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_9_REG, phyReg); }