/*************************************************************************** ** TNETD53xx Software Support ** Copyright(c) 2002, Texas Instruments Incorporated. All Rights Reserved. ** ** FILE: cpmdio.c ** ** DESCRIPTION: ** MDIO Polling State Machine API. Functions will enable mii-Phy ** negotiation. ** ** HISTORY: ** 01Jan01 Denis, Bill Original ** 27Mar02 Michael Hanrahan (modified from emacmdio.c) ** 07May02 Michael Hanrahan replaced clockwait for code delay ** 10Jul02 Michael Hanrahan more debug, if fallback link is selected *****************************************************************************/ #define __CPHAL_CPMDIO #include #include #include #include #include #include "mdio_reg.h" #include "adm6996.h" #include #if !defined(CONFIG_NO_PRINTK) #ifdef _CPHAL_CPMAC #define mdioPrintf PhyDev->HalDev->OsFunc->Printf #else #define mdioPrintf printk #endif #else /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ #define mdioPrintf(...) #endif /*--- #else ---*/ /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ #if !defined(CONFIG_MIPS_OHIO) #define CONFIG_MIPS_OHIO 0 #endif /*--- #if !defined(CONFIG_MIPS_OHIO) ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ extern unsigned int cpmac_switch; extern int cpmac_instances; extern struct cpmac_event_struct cpmac_event_data; extern void *cpmac_event_handle; static unsigned int cpmac_event_data_notify = 0; static unsigned int cpmac_event_data_last_update = 0; extern struct adm_struct adm_serial_register; static void cpmac_event_dataupdate(PHY_DEVICE *PhyDev); static void cpmac_event_update(void); /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ typedef struct _phy_device { bit32u miibase; bit32u inst; bit32u PhyState; bit32u MdixMask; bit32u PhyMask; bit32u MLinkMask; bit32u PhyMode; #ifdef _CPHAL_CPMAC HAL_DEVICE *HalDev; #endif # if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) unsigned int cpmac_switch; # endif /*--- #if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) ---*/ } _PHY_DEVICE; static void _mdioDelayEmulate(PHY_DEVICE *PhyDev, int ClockWait); static void _mdioWaitForAccessComplete(PHY_DEVICE *PhyDev); static void _mdioUserAccess(PHY_DEVICE *PhyDev, bit32u method, bit32u regadr, bit32u phyadr, bit32u data); static bit32u _mdioUserAccessRead(PHY_DEVICE *PhyDev, bit32u regadr, bit32u phyadr); static void _mdioUserAccessWrite(PHY_DEVICE *PhyDev, bit32u regadr, bit32u phyadr, bit32u data); static void _mdioDisablePhy(PHY_DEVICE *PhyDev,bit32u PhyNum); static void _mdioPhyTimeOut(PHY_DEVICE *PhyDev); static void _mdioResetPhy(PHY_DEVICE *PhyDev,bit32u PhyNum); static void _mdioDumpPhy(PHY_DEVICE *PhyDev, bit32u p); static void _mdioDumpState(PHY_DEVICE *PhyDev); /* Auto Mdix */ static void _mdioMdixDelay(PHY_DEVICE *PhyDev); static int _mdioMdixSupported(PHY_DEVICE *PhyDev); static void _MdioDefaultState (PHY_DEVICE *PhyDev); static void _MdioFindingState (PHY_DEVICE *PhyDev); static void _MdioFoundState (PHY_DEVICE *PhyDev); static void _MdioInitState (PHY_DEVICE *PhyDev); static void _MdioLinkedState (PHY_DEVICE *PhyDev); static void _MdioLinkWaitState (PHY_DEVICE *PhyDev); static void _MdioLoopbackState (PHY_DEVICE *PhyDev); static void _MdioNwayStartState(PHY_DEVICE *PhyDev); static void _MdioNwayWaitState (PHY_DEVICE *PhyDev); #ifndef TRUE #define TRUE (1==1) #endif #ifndef FALSE #define FALSE (1==2) #endif #define PHY_NOT_FOUND 0xFFFF /* Used in Phy Detection */ /*PhyState breakout */ #define PHY_DEV_OFFSET (0) #define PHY_DEV_SIZE (5) /* 5 Bits used */ #define PHY_DEV_MASK (0x1f<miibase) #define myMDIO_CONTROL MDIO_CONTROL (PhyDev->miibase) #define myMDIO_LINK MDIO_LINK (PhyDev->miibase) #define myMDIO_LINKINT MDIO_LINKINT (PhyDev->miibase) #define myMDIO_USERACCESS MDIO_USERACCESS(PhyDev->miibase, PhyDev->inst) #define myMDIO_USERPHYSEL MDIO_USERPHYSEL(PhyDev->miibase, PhyDev->inst) #define myMDIO_VER MDIO_VER (PhyDev->miibase) #ifndef VOLATILE32 #define VOLATILE32(addr) (*((volatile bit32u *)(addr))) #endif /************************************ *** *** Delays at least ClockWait cylces *** before returning *** **************************************/ void _mdioDelayEmulate(PHY_DEVICE *PhyDev, int ClockWait) { #ifdef _CPHAL_CPMAC /*+RC3.02*/ HAL_DEVICE *HalDev = PhyDev->HalDev; /*+RC3.02*/ osfuncSleep((int*)&ClockWait); /*+RC3.02*/ #else /*+RC3.02*/ volatile bit32u i=0; while(ClockWait--) { i |= myMDIO_LINK; /* MDIO register access to burn cycles */ } #endif } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void _mdioWaitForAccessComplete(PHY_DEVICE *PhyDev) { while((myMDIO_USERACCESS & MDIO_USERACCESS_GO)!=0) { } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void _mdioUserAccess(PHY_DEVICE *PhyDev, bit32u method, bit32u regadr, bit32u phyadr, bit32u data) { bit32u control; control = MDIO_USERACCESS_GO | (method) | (((regadr) << 21) & MDIO_USERACCESS_REGADR) | (((phyadr) << 16) & MDIO_USERACCESS_PHYADR) | ((data) & MDIO_USERACCESS_DATA); myMDIO_USERACCESS = control; } /************************************ *** *** Waits for MDIO_USERACCESS to be ready and reads data *** If 'WaitForData' set, waits for read to complete and returns Data, *** otherwise returns 0 *** Note: 'data' is 16 bits but we use 32 bits *** to be consistent with rest of the code. *** **************************************/ bit32u _mdioUserAccessRead(PHY_DEVICE *PhyDev, bit32u regadr, bit32u phyadr) { _mdioWaitForAccessComplete(PhyDev); /* Wait until UserAccess ready */ _mdioUserAccess(PhyDev, MDIO_USERACCESS_READ, regadr, phyadr, 0); _mdioWaitForAccessComplete(PhyDev); /* Wait for Read to complete */ return(myMDIO_USERACCESS & MDIO_USERACCESS_DATA); } /************************************ *** *** Waits for MDIO_USERACCESS to be ready and writes data *** **************************************/ void _mdioUserAccessWrite(PHY_DEVICE *PhyDev, bit32u regadr, bit32u phyadr, bit32u data) { _mdioWaitForAccessComplete(PhyDev); /* Wait until UserAccess ready */ _mdioUserAccess(PhyDev, MDIO_USERACCESS_WRITE, regadr, phyadr, data); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if !defined(CONFIG_NO_PRINTK) && 0 void _mdioDumpPhyDetailed(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; bit32u PhyNum; int RegData; # if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) if(cpmac_switch > 0) return; # endif /*--- #if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) ---*/ PhyNum = (*PhyState & PHY_DEV_MASK) >> PHY_DEV_OFFSET; /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ { int OUI = 0, Id = 0, Model = 0, Revision = 0; RegData = _mdioUserAccessRead(PhyDev, PHY_Identifier_2, PhyNum); Id = (RegData >> 10) & ((1 << 6) - 1); Model = (RegData >> 4) & ((1 << 6) - 1); Revision = (RegData >> 0) & ((1 << 4) - 1); mdioPrintf("[PHY %u] 0x%04x: ", PhyNum, RegData); switch(Id) { case 0: mdioPrintf("Internal Phy OUI=0x%X\n", OUI); break; case 5: RegData = _mdioUserAccessRead(PhyDev, PHY_Identifier_1, PhyNum); OUI = RegData << 3; RegData = _mdioUserAccessRead(PhyDev, PHY_Identifier_2, PhyNum); OUI |= ((RegData >> 10) & ((1 << 6) - 1)) << 19; mdioPrintf("External Phy (MICREL KS8721BL/SL) OUI=0x%X Model %u Revision %u \n", OUI, Model, Revision); break; case 51: RegData = _mdioUserAccessRead(PhyDev, PHY_Identifier_1, PhyNum); OUI = RegData; RegData = _mdioUserAccessRead(PhyDev, PHY_Identifier_2, PhyNum); OUI |= ((RegData >> 10) & ((1 << 6) - 1)) << 16; mdioPrintf("External Phy (Infineon-ADMtek ADM7001) OUI=0x%X Model %u Revision %u \n", OUI, Model, Revision); break; default: mdioPrintf("External Phy (unknown Id: %u) Model %u Revision %u \n", Id, Model, Revision); break; } } RegData = _mdioUserAccessRead(PhyDev, PHY_CONTROL_REG, PhyNum); mdioPrintf("[%u] PhyControl: %04X, Lookback=%s, Speed=%s, Duplex=%s\n", PhyNum, RegData, RegData & PHY_LOOP ? "On" : "Off", RegData & PHY_100 ? "100" : "10", RegData & PHY_FD ? "Full" : "Half"); RegData = _mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum); mdioPrintf("[%u] PhyStatus: %04X, AutoNeg=%s, Link=%s\n", PhyNum, RegData, RegData & NWAY_COMPLETE ? "Complete" : "NotComplete", RegData & PHY_LINKED ? "Up" : "Down"); RegData = _mdioUserAccessRead(PhyDev, NWAY_ADVERTIZE_REG, PhyNum); mdioPrintf("[%u] PhyMyCapability: %04X, 100FD=%s, 100HD=%s, 10FD=%s, 10HD=%s\n", PhyNum, RegData, RegData & NWAY_FD100 ? "Yes" : "No", RegData & NWAY_HD100 ? "Yes" : "No", RegData & NWAY_FD10 ? "Yes" : "No", RegData & NWAY_HD10 ? "Yes" : "No"); RegData = _mdioUserAccessRead(PhyDev, NWAY_REMADVERTISE_REG, PhyNum); mdioPrintf("[%u] PhyPartnerCapability: %04X, 100FD=%s, 100HD=%s, 10FD=%s, 10HD=%s\n", PhyNum, RegData, RegData & NWAY_FD100 ? "Yes" : "No", RegData & NWAY_HD100 ? "Yes" : "No", RegData & NWAY_FD10 ? "Yes" : "No", RegData & NWAY_HD10 ? "Yes" : "No"); RegData = _mdioUserAccessRead(PhyDev, PHY_GENERIC_CONFIG_REG, PhyNum); mdioPrintf("[%u] Generic Configuration Register: %04X, IFSEL %s LBKMD %s FLTLED %s CONV %s XOVEN %s ENREG8 %s DISPMG %s\n", PhyNum, RegData, (RegData & PHY_IFSEL) == (0 << 14) ? "MII" : (RegData & PHY_IFSEL) == (1 << 14) ? "GPSI" : "unknown", (RegData & PHY_LBKMD) == (0 << 12) ? "disable loop back" : (RegData & PHY_LBKMD) == (1 << 12) ? "PCS Layer loop back mode" : (RegData & PHY_LBKMD) == (3 << 12) ? "PMD Layer loop back mode" : "unknown loop back mode", (RegData & PHY_FLTLED) ? "enable" : "disable", (RegData & PHY_CONV) ? "converter mode" : "normal mode", (RegData & PHY_XOVEN) ? "mdix enable" : "mdix disable", (RegData & PHY_ENREG8) ? "enable register 8" : "enable store in register 5", (RegData & PHY_DISPMG) ? "disable medium on is high all the time" : "enable medium detect"); mdioPrintf("---------------------------------------------\n"); } #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if !defined(CONFIG_NO_PRINTK) void _mdioDumpPhy(PHY_DEVICE *PhyDev, bit32u p) { /*--- bit32u j,n; ---*/ /*--- bit32u PhyRegAddr; ---*/ /*--- bit32u phy_num; ---*/ bit32u PhyAcks, PhyMask = PhyDev->PhyMask; PhyAcks=myMDIO_ALIVE; PhyAcks&=PhyMask; /* Only interested in 'our' Phys */ #if 0 for(phy_num=0,j=1;phy_num<32;phy_num++,j<<=1) { if (PhyAcks&j) { mdioPrintf("%2d%s:",phy_num, (phy_num == p) ? ">" : " "); for(PhyRegAddr=0;PhyRegAddr<6;PhyRegAddr++) { n = _mdioUserAccessRead(PhyDev, PhyRegAddr, phy_num); mdioPrintf(" %04x",n&0x0ffff); } mdioPrintf("\n"); } } #endif /*--- _mdioDumpPhyDetailed(PhyDev); ---*/ } #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if !defined(CONFIG_NO_PRINTK) void _mdioDumpState(PHY_DEVICE *PhyDev) { bit32u state = PhyDev->PhyState; if (!cpMacDebug) return; mdioPrintf("Phy: %d, ",(state&PHY_DEV_MASK)>>PHY_DEV_OFFSET); mdioPrintf("State: %d/%s, ",(state&PHY_STATE_MASK)>>PHY_STATE_OFFSET,lstate[(state&PHY_STATE_MASK)>>PHY_STATE_OFFSET]); mdioPrintf("Speed: %d, ",(state&PHY_SPEED_MASK)>>PHY_SPEED_OFFSET); mdioPrintf("Dup: %d, ",(state&PHY_DUPLEX_MASK)>>PHY_DUPLEX_OFFSET); mdioPrintf("Tim: %d, ",(state&PHY_TIM_MASK)>>PHY_TIM_OFFSET); mdioPrintf("SMode: %d, ",(state&PHY_SMODE_MASK)>>PHY_SMODE_OFFSET); mdioPrintf("Chng: %d",(state&PHY_CHNG_MASK)>>PHY_CHNG_OFFSET); mdioPrintf("\n"); if (((state & PHY_STATE_MASK) != FINDING) && ((state & PHY_STATE_MASK) != INIT)) _mdioDumpPhy(PhyDev, (state & PHY_DEV_MASK) >> PHY_DEV_OFFSET); } #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void _mdioResetPhy(PHY_DEVICE *PhyDev,bit32u PhyNum) { bit16u PhyControlReg; _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, PHY_RESET); #if !defined(CONFIG_NO_PRINTK) if (cpMacDebug) mdioPrintf("cpMacMdioPhYReset(%d)\n",PhyNum); #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ /* Read control register until Phy Reset is complete */ do { PhyControlReg = _mdioUserAccessRead(PhyDev, PHY_CONTROL_REG, PhyNum); } while (PhyControlReg & PHY_RESET); /* Wait for Reset to clear */ } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void _mdioDisablePhy(PHY_DEVICE *PhyDev,bit32u PhyNum) { _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, PHY_ISOLATE|PHY_PDOWN); #if !defined(CONFIG_NO_PRINTK) if (cpMacDebug) mdioPrintf("cpMacMdioDisablePhy(%d)\n",PhyNum); #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void _MdioInitState(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; bit32u CurrentState; CurrentState=*PhyState; CurrentState=(CurrentState&~PHY_TIM_MASK)|(PHY_FIND_TO); CurrentState=(CurrentState&~PHY_STATE_MASK)|(FINDING); CurrentState=(CurrentState&~PHY_SPEED_MASK); CurrentState=(CurrentState&~PHY_DUPLEX_MASK); # if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) /* Je nach Hardware cpmac_switch setzen */ switch(cpmac_switch) { case 0: PhyDev->cpmac_switch = 0; break; case 1: /* 3070 mit internem (nicht zu verwendenden) und externem PHY */ if(PhyDev->inst == 1) PhyDev->cpmac_switch = 1; else PhyDev->cpmac_switch = 0; break; case 2: /* 3070 mit OHIO, also nur einem PHY */ if((CONFIG_MIPS_OHIO != 1) || (PhyDev->inst != 0)) { PhyDev->cpmac_switch = 0; # if !defined(CONFIG_NO_PRINTK) mdioPrintf("[cpmac] _MdioInitState: Illegal configuration for cpmac_switch.\n"); # endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ } else { PhyDev->cpmac_switch = 1; } break; default: # if !defined(CONFIG_NO_PRINTK) mdioPrintf("[cpmac] _MdioInitState: Unknown cpmac_switch value: %u\n", cpmac_switch); # endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ PhyDev->cpmac_switch = 0; break; } if(PhyDev->cpmac_switch == 1) { unsigned int RegData; CurrentState = 0; CurrentState = (CurrentState&~PHY_TIM_MASK); CurrentState = (CurrentState & ~PHY_DEV_MASK) | ((1 & PHY_DEV_MASK) << PHY_DEV_OFFSET); RegData = ADM_GET_SERIAL_REG(REG_ADM_STATUS1); CurrentState = CurrentState & ~PHY_SPEED_MASK; if(RegData & ADM_STATUS1_PORT5_SPEED) CurrentState |= 1 << PHY_SPEED_OFFSET; /* 100 MBit auf dem MII */ CurrentState = CurrentState & ~PHY_DUPLEX_MASK; if(RegData & ADM_STATUS1_PORT5_DUPLEX) CurrentState |= 1 << PHY_DUPLEX_OFFSET; /* full duplex */ adm_vlan_fbox_reset(); CurrentState = (CurrentState & ~PHY_STATE_MASK) | (NWAY_WAIT); } # endif /*--- #if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) ---*/ CurrentState|=PHY_CHANGE; *PhyState=CurrentState; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void _MdioFindingState(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; bit32u PhyMask = PhyDev->PhyMask; bit32u PhyNum,i,j,PhyAcks; PhyNum=PHY_NOT_FOUND; if (*PhyState&PHY_TIM_MASK) { *PhyState=(*PhyState&~PHY_TIM_MASK)|((*PhyState&PHY_TIM_MASK)-(1<miibase, myMDIO_ALIVE); } #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ *PhyState|=PHY_RECK_TO; /* This state currently has no support?*/ } } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void _MdioFoundState(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; bit32u PhyMask = PhyDev->PhyMask; bit32u MLinkMask = PhyDev->MLinkMask; bit32u PhyNum,PhyStatus,NWAYadvertise,m,phynum,i,j,PhyAcks; bit32u PhySel; if ((*PhyState&PHY_SMODE_MASK)==0) return; PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET; PhyAcks=myMDIO_ALIVE; PhyAcks&=PhyMask; /* Only interested in 'our' Phys */ /* Will now isolate all our Phys, except the one we have decided to use */ for(phynum=0,j=1;phynum<32;phynum++,j<<=1) { if (PhyAcks&j) { if (phynum!=PhyNum) /* Do not disabled Found Phy */ _mdioDisablePhy(PhyDev,phynum); } } /* Reset the Phy and proceed with auto-negotiation */ _mdioResetPhy(PhyDev,PhyNum); /* Now setup the MDIOUserPhySel register */ PhySel=PhyNum; /* Set the phy address */ /* Set the way Link will be Monitored */ /* Check the Link Selection Method */ if ((1 << PhyNum) & MLinkMask) PhySel |= MDIO_USERPHYSEL_LINKSEL; myMDIO_USERPHYSEL = PhySel; /* update PHYSEL */ /* Get the Phy Status */ PhyStatus = _mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum); #ifdef _CPHAL_CPMAC /* For Phy Internal loopback test, need to wait until Phy found, then set Loopback */ if (PhyDev->HalDev->MdioConnect & _CPMDIO_LOOPBK) { /* Set Phy in Loopback */ _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, PHY_LOOP|PHY_FD); /* Do a read to ensure PHY_LOOP has completed */ _mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum); *PhyState=(*PhyState&~PHY_STATE_MASK)|(LOOPBACK); *PhyState|=PHY_CHANGE; return; } #endif #if !defined(CONFIG_NO_PRINTK) if (cpMacDebug) mdioPrintf("Enable Phy to negotiate external connection\n"); #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ NWAYadvertise=NWAY_SEL; if (*PhyState&SMODE_FD100) NWAYadvertise|=NWAY_FD100; if (*PhyState&SMODE_HD100) NWAYadvertise|=NWAY_HD100; if (*PhyState&SMODE_FD10) NWAYadvertise|=NWAY_FD10; if (*PhyState&SMODE_HD10) NWAYadvertise|=NWAY_HD10; *PhyState&=~(PHY_TIM_MASK|PHY_STATE_MASK); if ((PhyStatus&NWAY_CAPABLE)&&(*PhyState&SMODE_AUTO)) { /*NWAY Phy Detected*/ /*For NWAY compliant Phys */ _mdioUserAccessWrite(PhyDev, NWAY_ADVERTIZE_REG, PhyNum, NWAYadvertise); #if !defined(CONFIG_NO_PRINTK) if (cpMacDebug) { mdioPrintf("NWAY Advertising: "); if (NWAYadvertise&NWAY_FD100) mdioPrintf("FullDuplex-100 "); if (NWAYadvertise&NWAY_HD100) mdioPrintf("HalfDuplex-100 "); if (NWAYadvertise&NWAY_FD10) mdioPrintf("FullDuplex-10 "); if (NWAYadvertise&NWAY_HD10) mdioPrintf("HalfDuplex-10 "); mdioPrintf("\n"); } #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, AUTO_NEGOTIATE_EN); _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, AUTO_NEGOTIATE_EN|RENEGOTIATE); *PhyState|=PHY_CHANGE|PHY_NWST_TO|NWAY_START; } else { *PhyState&=~SMODE_AUTO; /*The Phy is not capable of auto negotiation! */ m=NWAYadvertise; for(j=0x8000,i=0;(i<16)&&((j&m)==0);i++,j>>=1); m=j; j=0; if (m&(NWAY_FD100|NWAY_HD100)) { j=PHY_100; m&=(NWAY_FD100|NWAY_HD100); } if (m&(NWAY_FD100|NWAY_FD10)) j |= PHY_FD; #if !defined(CONFIG_NO_PRINTK) if (cpMacDebug) mdioPrintf("Requested PHY mode %s Duplex %s Mbps\n",(j&PHY_FD)?"Full":"Half",(j&PHY_100)?"100":"10"); #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, j); *PhyState &= ~PHY_SPEED_MASK; if (j&PHY_100) *PhyState|=(1<PhyState; bit32u PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET; PhyControlReg = _mdioUserAccessRead(PhyDev, PHY_GENERIC_STATUS_REG, PhyNum); if(PhyControlReg & PHY_STATUS_MD) { /* Reset state machine to FOUND */ *PhyState=(*PhyState&~PHY_STATE_MASK)|(FOUND); } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void _MdioNwayStartState(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; bit32u PhyNum,PhyMode; PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET; /*Wait for Negotiation to start */ PhyMode=_mdioUserAccessRead(PhyDev, PHY_CONTROL_REG, PhyNum); if((PhyMode&RENEGOTIATE)==0) { _mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum); /*Flush pending latch bits*/ *PhyState&=~(PHY_STATE_MASK|PHY_TIM_MASK); *PhyState|=PHY_CHANGE|NWAY_WAIT|PHY_NWDN_TO; _mdioMdixDelay(PhyDev); /* If AutoMdix add delay */ } else { if (*PhyState&PHY_TIM_MASK) *PhyState=(*PhyState&~PHY_TIM_MASK)|((*PhyState&PHY_TIM_MASK)-(1<PhyState; bit32u PhyNum,PhyStatus,NWAYadvertise,NWAYREadvertise,NegMode,i,j; # if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) if(PhyDev->cpmac_switch == 1) { /* Negotiation nicht notwendig */ *PhyState=(*PhyState&~PHY_STATE_MASK)|LINK_WAIT; *PhyState|=PHY_CHANGE; return; } # endif /*--- #if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) ---*/ PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET; PhyStatus=_mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum); if (PhyStatus&NWAY_COMPLETE) { *PhyState|=PHY_CHANGE; *PhyState&=~PHY_SPEED_MASK; *PhyState&=~PHY_DUPLEX_MASK; NWAYadvertise =_mdioUserAccessRead(PhyDev, NWAY_ADVERTIZE_REG, PhyNum); NWAYREadvertise =_mdioUserAccessRead(PhyDev, NWAY_REMADVERTISE_REG, PhyNum); /* Negotiated mode is we and the remote have in common */ NegMode = NWAYadvertise & NWAYREadvertise; #if !defined(CONFIG_NO_PRINTK) if (cpMacDebug) { mdioPrintf("Phy: %d, ",(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET); mdioPrintf("NegMode %04X, NWAYadvertise %04X, NWAYREadvertise %04X\n", NegMode, NWAYadvertise, NWAYREadvertise); } #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ /* Limit negotiation to fields below */ NegMode &= (NWAY_FD100|NWAY_HD100|NWAY_FD10|NWAY_HD10); if (NegMode==0) { NegMode=(NWAY_HD100|NWAY_HD10)&NWAYadvertise; /*or 10 ?? who knows, Phy is not MII compliant*/ #if !defined(CONFIG_NO_PRINTK) if(cpMacDebug) { mdioPrintf("Mdio:WARNING: Negotiation complete but NO agreement, default is HD\n"); /*--- _mdioDumpPhyDetailed(PhyDev); ---*/ } #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ } for(j=0x8000,i=0;(i<16)&&((j&NegMode)==0);i++,j>>=1); NegMode=j; #if !defined(CONFIG_NO_PRINTK) if (cpMacDebug) { mdioPrintf("Negotiated connection: "); if (NegMode&NWAY_FD100) mdioPrintf("FullDuplex 100 Mbps\n"); if (NegMode&NWAY_HD100) mdioPrintf("HalfDuplex 100 Mbps\n"); if (NegMode&NWAY_FD10) mdioPrintf("FullDuplex 10 Mbps\n"); if (NegMode&NWAY_HD10) mdioPrintf("HalfDuplex 10 Mbps\n"); } #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ if (NegMode!=0) { if (PhyStatus&PHY_LINKED) *PhyState=(*PhyState&~PHY_STATE_MASK)|LINKED; else *PhyState=(*PhyState&~PHY_STATE_MASK)|LINK_WAIT; if (NegMode&(NWAY_FD100|NWAY_HD100)) *PhyState=(*PhyState&~PHY_SPEED_MASK)|(1<PhyState; bit32u PhyStatus; bit32u PhyNum; # if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) if(PhyDev->cpmac_switch == 1) { if(ADM_GET_SERIAL_REG(REG_ADM_STATUS0) & ( ADM_STATUS0_PORT0_LINKUP | ADM_STATUS0_PORT1_LINKUP | ADM_STATUS0_PORT2_LINKUP | ADM_STATUS0_PORT3_LINKUP)) { *PhyState=(*PhyState&~PHY_STATE_MASK)|LINKED; *PhyState|=PHY_CHANGE; cpmac_event_dataupdate(PhyDev); /* Status changed to LINKED */ } else { if (*PhyState&PHY_TIM_MASK) { *PhyState=(*PhyState&~PHY_TIM_MASK)|((*PhyState&PHY_TIM_MASK)-(1<>PHY_DEV_OFFSET; PhyStatus=_mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum); if (PhyStatus&PHY_LINKED) { *PhyState=(*PhyState&~PHY_STATE_MASK)|LINKED; *PhyState|=PHY_CHANGE; cpmac_event_dataupdate(PhyDev); /* Status changed to LINKED */ } else { /* Ist der ADMtek-Anschluss verbunden? Ggf. in den Powerdown wechseln. */ if( (0x2e == (unsigned int) _mdioUserAccessRead(PhyDev, PHY_Identifier_1, PhyNum) && (0xcc60 == (((unsigned int) _mdioUserAccessRead(PhyDev, PHY_Identifier_2, PhyNum)) & 0xfff0)))) { bit16u PhyControlReg; PhyControlReg = _mdioUserAccessRead(PhyDev, PHY_GENERIC_STATUS_REG, PhyNum); if(!(PhyControlReg & PHY_STATUS_MD)) { _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, PHY_PDOWN); *PhyState=(*PhyState&~PHY_STATE_MASK)|(PDOWN); return; } } if (*PhyState&PHY_TIM_MASK) *PhyState=(*PhyState&~PHY_TIM_MASK)|((*PhyState&PHY_TIM_MASK)-(1<PhyState; /* Indicate MDI/MDIX mode switch is needed */ *PhyState|=PHY_MDIX_SWITCH; /* Toggle the MDIX mode indicatir */ if(*PhyState & PHY_MDIX) *PhyState &= ~PHY_MDIX_MASK; /* Current State is MDIX, set to MDI */ else *PhyState |= PHY_MDIX_MASK; /* Current State is MDI, set to MDIX */ /* Reset state machine to FOUND */ *PhyState=(*PhyState&~PHY_STATE_MASK)|(FOUND); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void _MdioLoopbackState(PHY_DEVICE *PhyDev) { return; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void _MdioLinkedState(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; bit32u PhyNum = (*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET; # if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) if(PhyDev->cpmac_switch == 1) { if(ADM_GET_SERIAL_REG(REG_ADM_STATUS0) & ( ADM_STATUS0_PORT0_LINKUP | ADM_STATUS0_PORT1_LINKUP | ADM_STATUS0_PORT2_LINKUP | ADM_STATUS0_PORT3_LINKUP)) { cpmac_event_dataupdate(PhyDev); /* Linked ports could have changed */ return; } } else # endif /*--- #if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) ---*/ { if (myMDIO_LINK&(1<cpmac_switch == 1)) # endif /*--- #if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) ---*/ _mdioMdixDelay(PhyDev); /* If AutoMdix add delay */ } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void _MdioDefaultState(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; /*Awaiting a cpMacMdioInit call */ *PhyState|=PHY_CHANGE; } /*User Calls********************************************************* */ void cpMacMdioClose(PHY_DEVICE *PhyDev, int Full) { } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ int cpMacMdioInit(PHY_DEVICE *PhyDev, bit32u miibase, bit32u inst, bit32u PhyMask, bit32u MLinkMask, bit32u MdixMask, bit32u ResetReg, bit32u ResetBit, bit32u MdioBusFreq, bit32u MdioClockFreq, int verbose, void *Info) { bit32u HighestChannel; bit32u ControlState; bit32u *PhyState = &PhyDev->PhyState; bit32u clkdiv; /*MJH+030328*/ cpMacDebug=verbose; /*--- cpMacDebug = 1; ---*/ PhyDev->miibase = miibase; PhyDev->inst = inst; PhyDev->PhyMask = PhyMask; PhyDev->MLinkMask = MLinkMask; PhyDev->MdixMask = MdixMask; # ifdef _CPHAL_CPMAC PhyDev->HalDev = (HAL_DEVICE*) Info; # endif *PhyState &= ~PHY_MDIX_MASK; /* Set initial State to MDI */ /* Check that the channel supplied is within range */ HighestChannel = (myMDIO_CONTROL & MDIO_CONTROL_HIGHEST_USER_CHANNEL) > 8; if(inst > HighestChannel) return(HighestChannel); /*Setup MII MDIO access regs */ /* Calculate the correct value for the mclkdiv */ /* See PITS #14 */ if (MdioClockFreq) /*MJH+030402*/ clkdiv = (MdioBusFreq / MdioClockFreq) - 1; /*MJH+030402*/ else /*MJH+030402*/ clkdiv = 0xFF; /*MJH+030402*/ /*--- printk("[MDIO] (%u) MdioBusFreq %u MdioClockFreq %u\n", inst, MdioBusFreq, MdioClockFreq); ---*/ ControlState = MDIO_CONTROL_ENABLE; ControlState |= (clkdiv & MDIO_CONTROL_CLKDIV); /*MJH+030328*/ /* If mii is not out of reset or if the Control Register is not set correctly then initalize */ if( !(VOLATILE32(ResetReg) & (1 << ResetBit)) || ((myMDIO_CONTROL & (MDIO_CONTROL_CLKDIV | MDIO_CONTROL_ENABLE)) != ControlState) )/*GSG~030404*/ { /* MII not setup, Setup initial condition */ VOLATILE32(ResetReg) &= ~(1 << ResetBit); _mdioDelayEmulate(PhyDev, 64); VOLATILE32(ResetReg) |= (1 << ResetBit); /* take mii out of reset */ _mdioDelayEmulate(PhyDev, 64); myMDIO_CONTROL = ControlState; /* Enable MDIO */ } /*--- printk("[MDIO]: (%u) myMDIO_CONTROL(&=0x%x)=0x%x\n", inst, &(myMDIO_CONTROL), myMDIO_CONTROL); ---*/ *PhyState=INIT; # if !defined(CONFIG_NO_PRINTK) if (cpMacDebug) mdioPrintf("cpMacMdioInit\n"); _mdioDumpState(PhyDev); # endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ return(0); } void cpMacMdioSetPhyMode(PHY_DEVICE *PhyDev,bit32u PhyMode) { bit32u *PhyState = &PhyDev->PhyState; bit32u CurrentState; PhyDev->PhyMode = PhyMode; /* used for AUTOMIDX, planned to replace PhyState fields */ *PhyState&=~PHY_SMODE_MASK; if (PhyMode&NWAY_AUTO) *PhyState|=SMODE_AUTO; if (PhyMode&NWAY_FD100) *PhyState|=SMODE_FD100; if (PhyMode&NWAY_HD100) *PhyState|=SMODE_HD100; if (PhyMode&NWAY_FD10) *PhyState|=SMODE_FD10; if (PhyMode&NWAY_HD10) *PhyState|=SMODE_HD10; CurrentState=*PhyState&PHY_STATE_MASK; if ((CurrentState==NWAY_START)|| (CurrentState==NWAY_WAIT) || (CurrentState==LINK_WAIT) || (CurrentState==LINKED) ) *PhyState=(*PhyState&~PHY_STATE_MASK)|FOUND|PHY_CHANGE; #if !defined(CONFIG_NO_PRINTK) if (cpMacDebug) mdioPrintf("cpMacMdioSetPhyMode:%08X Auto:%d, FD10:%d, HD10:%d, FD100:%d, HD100:%d\n", PhyMode, PhyMode&NWAY_AUTO, PhyMode&NWAY_FD10, PhyMode&NWAY_HD10, PhyMode&NWAY_FD100, PhyMode&NWAY_HD100); _mdioDumpState(PhyDev); #endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ } /* cpMacMdioTic is called every 10 mili seconds to process Phy states */ int cpMacMdioTic(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; bit32u CurrentState; /* Act on current state of the Phy */ cpmac_event_data_last_update++; if(cpmac_event_data_notify && (cpmac_event_data_last_update > 100)) cpmac_event_update(); CurrentState=*PhyState; switch(CurrentState&PHY_STATE_MASK) { case INIT: _MdioInitState(PhyDev); break; case FINDING: _MdioFindingState(PhyDev); break; case FOUND: _MdioFoundState(PhyDev); break; case PDOWN: _MdioPdownState(PhyDev); break; case NWAY_START: _MdioNwayStartState(PhyDev); break; case NWAY_WAIT: _MdioNwayWaitState(PhyDev); break; case LINK_WAIT: _MdioLinkWaitState(PhyDev); break; case LINKED: _MdioLinkedState(PhyDev); break; case LOOPBACK: _MdioLoopbackState(PhyDev); break; default: _MdioDefaultState(PhyDev); break; } /*Dump state info if a change has been detected */ # if !defined(CONFIG_NO_PRINTK) /*--- if ((CurrentState&~PHY_TIM_MASK)!=(*PhyState&~PHY_TIM_MASK)) { ---*/ /*--- bit32u PhyNum = (*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET; ---*/ /*--- if( (0x2e == (unsigned int) _mdioUserAccessRead(PhyDev, PHY_Identifier_1, PhyNum) ---*/ /*--- && (0xcc60 == (((unsigned int) _mdioUserAccessRead(PhyDev, PHY_Identifier_2, PhyNum)) & 0xfff0)))) { ---*/ # if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) /*--- if(cpMacDebug) { ---*/ /*--- if((PhyDev->inst == 1) && (cpmac_switch == 1)) { ---*/ /*--- printk("**** PHY %u changed state from %s to %s ****\n", ---*/ /*--- PhyNum, ---*/ /*--- lstate[((CurrentState&~PHY_TIM_MASK)&PHY_STATE_MASK)>>PHY_STATE_OFFSET], ---*/ /*--- lstate[((*PhyState&~PHY_TIM_MASK)&PHY_STATE_MASK)>>PHY_STATE_OFFSET]); ---*/ /*--- } ---*/ /*--- } ---*/ # endif /*--- #if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) ---*/ /*--- _mdioDumpState(PhyDev); ---*/ /*--- } ---*/ # endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ /* Check is MDI/MDIX mode switch is needed */ if(*PhyState & PHY_MDIX_SWITCH) { bit32u Mdix; *PhyState &= ~PHY_MDIX_SWITCH; /* Clear Mdix Flip indicator */ if(*PhyState & PHY_MDIX) Mdix = 1; else Mdix = 0; return(_MIIMDIO_MDIXFLIP|Mdix); } /*Return state change to user */ if (*PhyState&PHY_CHNG_MASK) { *PhyState&=~PHY_CHNG_MASK; return(1); } else return(0); } /* cpMacMdioGetDuplex is called to retrieve the Duplex info */ int cpMacMdioGetDuplex(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; return((*PhyState&PHY_DUPLEX_MASK)?1:0); /* return 0 or a 1 */ } /* cpMacMdioGetSpeed is called to retreive the Speed info */ int cpMacMdioGetSpeed(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; return(*PhyState&PHY_SPEED_MASK); } /* cpMacMdioGetPhyNum is called to retreive the Phy Device Adr info */ int cpMacMdioGetPhyNum(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; return((*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET); } /* cpMacMdioGetLoopback is called to Determine if the LOOPBACK state has been reached*/ int cpMacMdioGetLoopback(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; return((*PhyState&PHY_STATE_MASK)==LOOPBACK); } /* cpMacMdioGetLinked is called to Determine if the LINKED state has been reached*/ int cpMacMdioGetLinked(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; return((*PhyState&PHY_STATE_MASK)==LINKED); } void cpMacMdioLinkChange(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; bit32u PhyNum,PhyStatus; PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET; if (cpMacMdioGetLinked(PhyDev)) { PhyStatus=_mdioUserAccessRead(PhyDev, PHY_STATUS_REG, PhyNum); if ((PhyStatus&PHY_LINKED)==0) { *PhyState&=~(PHY_TIM_MASK|PHY_STATE_MASK); if (*PhyState&SMODE_AUTO) { _mdioUserAccessWrite(PhyDev, PHY_CONTROL_REG, PhyNum, AUTO_NEGOTIATE_EN|RENEGOTIATE); *PhyState|=PHY_CHANGE|PHY_NWST_TO|NWAY_START; } else { *PhyState|=PHY_CHANGE|PHY_LINK_TO|LINK_WAIT; } } } } void cpMacMdioGetVer(bit32u miibase, bit32u *ModID, bit32u *RevMaj, bit32u *RevMin) { bit32u Ver; Ver = MDIO_VER(miibase); *ModID = (Ver & MDIO_VER_MODID) >> 16; *RevMaj = (Ver & MDIO_VER_REVMAJ) >> 8; *RevMin = (Ver & MDIO_VER_REVMIN); } int cpMacMdioGetPhyDevSize(void) { return(sizeof(PHY_DEVICE)); } /* returns 0 if current Phy has AutoMdix support, otherwise 0 */ int _mdioMdixSupported(PHY_DEVICE *PhyDev) { bit32u *PhyState = &PhyDev->PhyState; bit32u PhyNum; if((PhyDev->PhyMode & NWAY_AUTOMDIX) == 0) return(0); /* AutoMdix not turned on */ PhyNum=(*PhyState&PHY_DEV_MASK)>>PHY_DEV_OFFSET; if( ((1<MdixMask) == 0) return(0); /* Phy does not support AutoMdix*/ return(1); } /* If current Phy has AutoMdix support add Mdix Delay to the Timer State Value */ void _mdioMdixDelay(PHY_DEVICE *PhyDev) { int Delay; bit32u *PhyState = &PhyDev->PhyState; #ifdef _CPHAL_CPMAC HAL_DEVICE *HalDev = PhyDev->HalDev; #endif if(_mdioMdixSupported(PhyDev) == 0) return; /* AutoMdix not supported */ /* Currently only supported when used with the CPMAC */ #ifdef _CPHAL_CPMAC /* Get the Delay value in milli-seconds and convert to ten-milli second value */ Delay = cpmacRandomRange(HalDev, _AUTOMDIX_DELAY_MIN, _AUTOMDIX_DELAY_MAX); Delay /= 10; /* Add AutoMidx Random Switch Delay to AutoMdix Link Delay */ Delay += (PHY_MDIX_TO>>PHY_TIM_OFFSET); /* Change Timeout value to AutoMdix standard */ *PhyState &= ~(PHY_TIM_MASK); /* Clear current Time out value */ *PhyState |= (Delay<data), data, data_size); event_struct->event_header.id = avm_event_id_ethernet_status; event_struct->chiptype = avm_event_ethernet_chip_adm6696l; avm_event_source_trigger(cpmac_event_handle, avm_event_id_ethernet_status, sizeof(struct cpmac_event_struct_verbose), (void *) event_struct); } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void cpmac_event_notify(void *context, enum _avm_event_id id) { switch(id) { case avm_event_id_ethernet_connect_status: cpmac_event_update(); break; case avm_event_id_ethernet_status: cpmac_event_update_detail(); break; default: # if !defined(CONFIG_NO_PRINTK) printk("cpmac_event_notify: Unknown event ID %u!\n", id); # endif /*--- #if !defined(CONFIG_NO_PRINTK) ---*/ break; } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void cpmac_event_dataupdate(PHY_DEVICE *PhyDev) { bit32u state = PhyDev->PhyState; unsigned int notify; notify = cpmac_event_data_notify; # if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) if(cpmac_switch != 0) { if(PhyDev->cpmac_switch == 1) { /* !!! Enabled status too expensive to ask for !!! */ /*--- unsigned int i, j = 0; ---*/ unsigned int RegData; /*--- for(i = REG_ADM_CONF_PORT0; i <= REG_ADM_CONF_PORT3; i++) { ---*/ /*--- switch(i) { ---*/ /*--- case REG_ADM_CONF_PORT0: ---*/ /*--- case REG_ADM_CONF_PORT1: ---*/ /*--- case REG_ADM_CONF_PORT2: ---*/ /*--- case REG_ADM_CONF_PORT3: ---*/ /*--- RegData = ADM_GET_EEPROM_REG(i); ---*/ /*--- notify |= cpmac_event_data.port[j].enabled != ((!(RegData & ADM_CONF_PORT_DISABLE)) != 0); ---*/ /*--- cpmac_event_data.port[j].enabled = (!(RegData & ADM_CONF_PORT_DISABLE)) != 0; ---*/ /*--- j++; ---*/ /*--- break; ---*/ /*--- default: ---*/ /*--- break; ---*/ /*--- } ---*/ /*--- } ---*/ RegData = ADM_GET_SERIAL_REG(REG_ADM_STATUS0); cpmac_event_data_notify |= cpmac_event_data.port[0].link != adm_serial_register.status.port0linkup; cpmac_event_data_notify |= cpmac_event_data.port[1].link != adm_serial_register.status.port1linkup; cpmac_event_data_notify |= cpmac_event_data.port[2].link != adm_serial_register.status.port2linkup; cpmac_event_data_notify |= cpmac_event_data.port[3].link != adm_serial_register.status.port3linkup; if(!cpmac_event_data_notify) /* Nothing changed? => We are ready. */ return; cpmac_event_data.port[0].link = adm_serial_register.status.port0linkup; cpmac_event_data.port[0].speed100 = adm_serial_register.status.port0speed; cpmac_event_data.port[0].fullduplex = adm_serial_register.status.port0duplex; cpmac_event_data.port[1].link = adm_serial_register.status.port1linkup; cpmac_event_data.port[1].speed100 = adm_serial_register.status.port1speed; cpmac_event_data.port[1].fullduplex = adm_serial_register.status.port1duplex; cpmac_event_data.port[2].link = adm_serial_register.status.port2linkup; cpmac_event_data.port[2].speed100 = adm_serial_register.status.port2speed; cpmac_event_data.port[2].fullduplex = adm_serial_register.status.port2duplex; cpmac_event_data.port[3].link = adm_serial_register.status.port3linkup; cpmac_event_data.port[3].speed100 = adm_serial_register.status.port3speed; cpmac_event_data.port[3].fullduplex = adm_serial_register.status.port3duplex; } else { /* Nothing to do for internal PHY when the switch is connected */ } return; } # endif /*--- #if defined(CONFIG_MIPS_AVALANCHE_CPMAC_ADM6996) ---*/ cpmac_event_data_notify |= cpmac_event_data.port[PhyDev->inst].link != ((state & PHY_STATE_MASK) == LINKED); /*--- cpmac_event_data.port[PhyDev->inst].enabled = 1; ---*/ cpmac_event_data.port[PhyDev->inst].link = (state & PHY_STATE_MASK) == LINKED; cpmac_event_data.port[PhyDev->inst].speed100 = (state & (NWAY_FD100 | NWAY_HD100)) != 0; cpmac_event_data.port[PhyDev->inst].fullduplex = (state & (NWAY_FD100 | NWAY_FD10)) != 0; }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ static void cpmac_event_update(void) { cpmac_event_data_notify = 0; cpmac_event_data_last_update = 0; # if 0 { unsigned int i; for(i = 0; i < cpmac_event_data.ports; i++) { /*--- printk("**** Notify Port %u: port %s, link %s, %s Mbps, %s duplex\n", ---*/ printk("**** Notify Port %u: link %s, %s Mbps, %s duplex\n", i, /*--- cpmac_event_data.port[i].enabled ? "enabled" : "disabled", ---*/ cpmac_event_data.port[i].link ? "up" : "down", cpmac_event_data.port[i].speed100 ? "100" : "10", cpmac_event_data.port[i].fullduplex ? "full" : "half"); } } # endif /*--- #if 0 ---*/ if(avm_event_source_check_id(cpmac_event_handle, avm_event_id_ethernet_connect_status)) { unsigned char *data; data = (unsigned char *) kmalloc(sizeof(struct cpmac_event_struct), GFP_ATOMIC); if(data == NULL) { printk("cpmac error: Could not allocate memory for status update\n"); return; } memcpy(data, (unsigned char *) &cpmac_event_data, sizeof(struct cpmac_event_struct)); avm_event_source_trigger(cpmac_event_handle, avm_event_id_ethernet_connect_status, sizeof(struct cpmac_event_struct), (void *) data); } }