/* * The following functions are initialisation functions taken from the Atmel * EMAC sample code. */ static portBASE_TYPE prvProbePHY (void) { unsigned portLONG ulPHYId1, ulPHYId2; //, ulStatus; portBASE_TYPE xReturn = pdPASS; /* Code supplied by Atmel (reformatted) ----------------- */ /* Enable management port */ AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE; AT91C_BASE_EMAC->EMAC_NCFGR |= (2) << 10; /* Read the PHY ID. */ vReadPHY (AT91C_PHY_ADDR, MII_PHYSID1, &ulPHYId1); vReadPHY (AT91C_PHY_ADDR, MII_PHYSID2, &ulPHYId2); /* AMD AM79C875: PHY_ID1 = 0x0022 PHY_ID2 = 0x5541 Bits 3:0 Revision Number Four bit manufacturer?s revision number. 0001 stands for Rev. A, etc. */ debug_printf ("PHY_ID1=%04X PHY_ID2=%04X\n", ulPHYId1, ulPHYId2); #if 0 if (((ulPHYId1 << 16) | (ulPHYId2 & 0xfff0)) != MII_DM9161_ID) { /* Did not expect this ID. */ xReturn = pdFAIL; } else { ulStatus = xGetLinkSpeed (); if (ulStatus != pdPASS) { xReturn = pdFAIL; } } #endif /* Disable management port */ AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE; /* End of code supplied by Atmel ------------------------ */ return xReturn; }
static portBASE_TYPE xGetLinkSpeed( void ) { unsigned long ulBMSR, ulBMCR, ulLPA, ulMACCfg, ulSpeed, ulDuplex; /* Code supplied by Atmel (reformatted) -----------------*/ /* Link status is latched, so read twice to get current value */ vReadPHY(AT91C_PHY_ADDR, MII_BMSR, &ulBMSR); vReadPHY(AT91C_PHY_ADDR, MII_BMSR, &ulBMSR); if( !( ulBMSR & BMSR_LSTATUS ) ) { /* No Link. */ return pdFAIL; } vReadPHY(AT91C_PHY_ADDR, MII_BMCR, &ulBMCR); if (ulBMCR & BMCR_ANENABLE) { /* AutoNegotiation is enabled. */ if (!(ulBMSR & BMSR_ANEGCOMPLETE)) { /* Auto-negotitation in progress. */ return pdFAIL; } vReadPHY(AT91C_PHY_ADDR, MII_LPA, &ulLPA); if( ( ulLPA & LPA_100FULL ) || ( ulLPA & LPA_100HALF ) ) { ulSpeed = SPEED_100; } else { ulSpeed = SPEED_10; } if( ( ulLPA & LPA_100FULL ) || ( ulLPA & LPA_10FULL ) ) { ulDuplex = DUPLEX_FULL; } else { ulDuplex = DUPLEX_HALF; } } else { ulSpeed = ( ulBMCR & BMCR_SPEED100 ) ? SPEED_100 : SPEED_10; ulDuplex = ( ulBMCR & BMCR_FULLDPLX ) ? DUPLEX_FULL : DUPLEX_HALF; } /* Update the MAC */ ulMACCfg = AT91C_BASE_EMAC->EMAC_NCFGR & ~( AT91C_EMAC_SPD | AT91C_EMAC_FD ); if( ulSpeed == SPEED_100 ) { if( ulDuplex == DUPLEX_FULL ) { /* 100 Full Duplex */ AT91C_BASE_EMAC->EMAC_NCFGR = ulMACCfg | AT91C_EMAC_SPD | AT91C_EMAC_FD; } else { /* 100 Half Duplex */ AT91C_BASE_EMAC->EMAC_NCFGR = ulMACCfg | AT91C_EMAC_SPD; } } else { if (ulDuplex == DUPLEX_FULL) { /* 10 Full Duplex */ AT91C_BASE_EMAC->EMAC_NCFGR = ulMACCfg | AT91C_EMAC_FD; } else { /* 10 Half Duplex */ AT91C_BASE_EMAC->EMAC_NCFGR = ulMACCfg; } } /* End of code supplied by Atmel ------------------------*/ return pdPASS; }
/* See the header file for descriptions of public functions. */ xSemaphoreHandle xEMACInit( void ) { /* Code supplied by Atmel -------------------------------*/ /* Disable pull up on RXDV => PHY normal mode (not in test mode), PHY has internal pull down. */ AT91C_BASE_PIOB->PIO_PPUDR = 1 << 15; #if USE_RMII_INTERFACE != 1 /* PHY has internal pull down : set MII mode. */ AT91C_BASE_PIOB->PIO_PPUDR = 1 << 16; #endif /* Clear PB18 <=> PHY powerdown. */ AT91C_BASE_PIOB->PIO_PER = 1 << 18; AT91C_BASE_PIOB->PIO_OER = 1 << 18; AT91C_BASE_PIOB->PIO_CODR = 1 << 18; /* After PHY power up, hardware reset. */ AT91C_BASE_RSTC->RSTC_RMR = emacRESET_KEY | emacRESET_LENGTH; AT91C_BASE_RSTC->RSTC_RCR = emacRESET_KEY | AT91C_RSTC_EXTRST; /* Wait for hardware reset end. */ while( !( AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL ) ) { __asm volatile ( "NOP" ); } __asm volatile ( "NOP" ); /* Setup the pins. */ AT91C_BASE_PIOB->PIO_ASR = emacPERIPHERAL_A_SETUP; AT91C_BASE_PIOB->PIO_PDR = emacPERIPHERAL_A_SETUP; /* Enable com between EMAC PHY. Enable management port. */ AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE; /* MDC = MCK/32. */ AT91C_BASE_EMAC->EMAC_NCFGR |= ( 2 ) << 10; /* Wait for PHY auto init end (rather crude delay!). */ vTaskDelay( emacPHY_INIT_DELAY ); /* PHY configuration. */ #if USE_RMII_INTERFACE != 1 { unsigned long ulControl; /* PHY has internal pull down : disable MII isolate. */ vReadPHY( AT91C_PHY_ADDR, MII_BMCR, &ulControl ); vReadPHY( AT91C_PHY_ADDR, MII_BMCR, &ulControl ); ulControl &= ~BMCR_ISOLATE; vWritePHY( AT91C_PHY_ADDR, MII_BMCR, ulControl ); } #endif /* Disable management port again. */ AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE; #if USE_RMII_INTERFACE != 1 /* Enable EMAC in MII mode, enable clock ERXCK and ETXCK. */ AT91C_BASE_EMAC->EMAC_USRIO = AT91C_EMAC_CLKEN ; #else /* Enable EMAC in RMII mode, enable RMII clock (50MHz from oscillator on ERFCK). */ AT91C_BASE_EMAC->EMAC_USRIO = AT91C_EMAC_RMII | AT91C_EMAC_CLKEN ; #endif /* End of code supplied by Atmel ------------------------*/ /* Setup the buffers and descriptors. */ prvSetupDescriptors(); /* Load our MAC address into the EMAC. */ prvSetupMACAddress(); /* Are we connected? */ if( prvProbePHY() ) { /* Enable the interrupt! */ portENTER_CRITICAL(); { prvSetupEMACInterrupt(); vPassEMACSemaphore( xSemaphore ); } portEXIT_CRITICAL(); } return xSemaphore; }