SAMV71 Xplained Ultra Software Package 1.3

gmacb_phy.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License 
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2013, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
00028  */
00029 
00030 /** \file */
00031 
00032 /*---------------------------------------------------------------------------
00033  *         Headers
00034  *---------------------------------------------------------------------------*/
00035 
00036 #include "board.h"
00037 
00038 /*---------------------------------------------------------------------------
00039  *         Definitions
00040  *---------------------------------------------------------------------------*/
00041 
00042 /** Default max retry count */
00043 #define GMACB_RETRY_MAX            300000
00044 
00045 /** Default max retry count */
00046 #define GACB_RETRY_MAX            1000000
00047 
00048 /*---------------------------------------------------------------------------
00049  *         Local functions
00050  *---------------------------------------------------------------------------*/
00051 
00052 
00053 /**
00054  * Wait PHY operation complete.
00055  * Return 1 if the operation completed successfully.
00056  * May be need to re-implemented to reduce CPU load.
00057  * \param retry: the retry times, 0 to wait forever until complete.
00058  */
00059 static uint8_t GMACB_WaitPhy( Gmac *pHw, uint32_t retry )
00060 {
00061     volatile uint32_t retry_count = 0;
00062 
00063     while (!GMAC_IsIdle(pHw))   {
00064         if(retry == 0) continue;
00065         retry_count ++;
00066         if (retry_count >= retry) {
00067             return 0;
00068         }
00069     }
00070     return 1;
00071 }
00072 
00073 /**
00074  * Read PHY register.
00075  * Return 1 if successfully, 0 if timeout.
00076  * \param pHw HW controller address
00077  * \param PhyAddress PHY Address
00078  * \param Address Register Address
00079  * \param pValue Pointer to a 32 bit location to store read data
00080  * \param retry The retry times, 0 to wait forever until complete.
00081  */
00082 static uint8_t GMACB_ReadPhy(Gmac *pHw,
00083         uint8_t PhyAddress,
00084         uint8_t Address,
00085         uint32_t *pValue,
00086         uint32_t retry)
00087 {
00088     GMAC_PHYMaintain(pHw, PhyAddress, Address, 1, 0);
00089     if ( GMACB_WaitPhy(pHw, retry) == 0 ) {
00090         TRACE_ERROR("TimeOut GMACB_ReadPhy\n\r");
00091         return 0;
00092     }
00093     *pValue = GMAC_PHYData(pHw);
00094     return 1;
00095 }
00096 
00097 /**
00098  * Write PHY register
00099  * Return 1 if successfully, 0 if timeout.
00100  * \param pHw HW controller address
00101  * \param PhyAddress PHY Address
00102  * \param Address Register Address
00103  * \param Value Data to write ( Actually 16 bit data )
00104  * \param retry The retry times, 0 to wait forever until complete.
00105  */
00106 static uint8_t GMACB_WritePhy(Gmac *pHw,
00107         uint8_t PhyAddress,
00108         uint8_t Address,
00109         uint32_t Value,
00110         uint32_t retry)
00111 {
00112     GMAC_PHYMaintain(pHw, PhyAddress, Address, 0, Value);
00113     if ( GMACB_WaitPhy(pHw, retry) == 0 ) {
00114         TRACE_ERROR("TimeOut GMACB_WritePhy\n\r");
00115         return 0;
00116     }
00117     return 1;
00118 }
00119 
00120 /*---------------------------------------------------------------------------
00121  *         Exported functions
00122  *---------------------------------------------------------------------------*/
00123 
00124 /**
00125  * \brief Find a valid PHY Address ( from 0 to 31 ).
00126  * \param pMacb Pointer to the MACB instance
00127  * \return 0xFF when no valid PHY Address found.
00128  */
00129 static uint8_t GMACB_FindValidPhy(GMacb *pMacb)
00130 {
00131     sGmacd *pDrv = pMacb->pGmacd;
00132     Gmac *pHw = pDrv->pHw;
00133 
00134     uint32_t  retryMax;
00135     uint32_t  value=0;
00136     uint8_t rc;
00137     uint8_t phyAddress;
00138     uint8_t cnt;
00139 
00140     TRACE_DEBUG("GMACB_FindValidPhy\n\r");
00141 
00142     GMAC_EnableMdio(pHw);
00143     phyAddress = pMacb->phyAddress;
00144     retryMax = pMacb->retryMax;
00145 
00146     /* Check current phyAddress */
00147     rc = phyAddress;
00148     if( GMACB_ReadPhy(pHw, phyAddress, GMII_PHYID1R, &value, retryMax) == 0 ) {
00149         TRACE_ERROR("GMACB PROBLEM\n\r");
00150     }
00151     TRACE_DEBUG("_PHYID1  : 0x%X, addr: %d\n\r", value, phyAddress);
00152 
00153     /* Find another one */
00154     if (value != GMII_OUI_MSB) {
00155         rc = 0xFF;
00156         for(cnt = 0; cnt < 32; cnt ++) {
00157             phyAddress = (phyAddress + 1) & 0x1F;
00158             if( GMACB_ReadPhy(pHw, phyAddress, GMII_PHYID1R, &value, retryMax) 
00159                         == 0 ){
00160                 TRACE_ERROR("MACB PROBLEM\n\r");
00161             }
00162             TRACE_DEBUG("_PHYID1  : 0x%X, addr: %d\n\r", value, phyAddress);
00163             if (value == GMII_OUI_MSB) {
00164 
00165                 rc = phyAddress;
00166                 break;
00167             }
00168         }
00169     }
00170     if (rc != 0xFF) {
00171         TRACE_INFO("** Valid PHY Found: %d\n\r", rc);
00172         GMACB_ReadPhy(pHw, phyAddress, GMII_PHYID1R, &value, retryMax);
00173         TRACE_DEBUG("_PHYID1R  : 0x%X, addr: %d\n\r", value, phyAddress);
00174         GMACB_ReadPhy(pHw, phyAddress, GMII_PHYID2R, &value, retryMax);
00175         TRACE_DEBUG("_EMSR  : 0x%X, addr: %d\n\r", value, phyAddress);
00176     }
00177     GMAC_DisableMdio(pHw);
00178     return rc;
00179 }
00180 
00181 
00182 /*----------------------------------------------------------------------------
00183  *        Exported functions
00184  *----------------------------------------------------------------------------*/
00185 
00186 
00187 /**
00188  * \brief Dump all the useful registers.
00189  * \param pMacb          Pointer to the MACB instance
00190  */
00191 void GMACB_DumpRegisters(GMacb *pMacb)
00192 {
00193     sGmacd *pDrv = pMacb->pGmacd;
00194     Gmac *pHw = pDrv->pHw;
00195 
00196     uint8_t phyAddress;
00197     uint32_t retryMax;
00198     uint32_t value;
00199 
00200     TRACE_INFO("GMACB_DumpRegisters\n\r");
00201 
00202     GMAC_EnableMdio(pHw);
00203     phyAddress = pMacb->phyAddress;
00204     retryMax = pMacb->retryMax;
00205 
00206     TRACE_INFO("GMII MACB @ %d) Registers:\n\r", phyAddress);
00207 
00208     GMACB_ReadPhy(pHw, phyAddress, GMII_BMCR, &value, retryMax);
00209     TRACE_INFO(" _BMCR     : 0x%X\n\r", (unsigned)value);
00210     GMACB_ReadPhy(pHw, phyAddress, GMII_BMSR, &value, retryMax);
00211     TRACE_INFO(" _BMSR     : 0x%X\n\r", (unsigned)value);
00212     GMACB_ReadPhy(pHw, phyAddress, GMII_PHYID1R, &value, retryMax);
00213     TRACE_INFO(" _PHYID1     : 0x%X\n\r", (unsigned)value);
00214     GMACB_ReadPhy(pHw, phyAddress, GMII_PHYID2R, &value, retryMax);
00215     TRACE_INFO(" _PHYID2     : 0x%X\n\r", (unsigned)value);
00216     GMACB_ReadPhy(pHw, phyAddress, GMII_ANAR, &value, retryMax);
00217     TRACE_INFO(" _ANAR     : 0x%X\n\r", (unsigned)value);
00218     GMACB_ReadPhy(pHw, phyAddress, GMII_ANLPAR, &value, retryMax);
00219     TRACE_INFO(" _ANLPAR   : 0x%X\n\r", (unsigned)value);
00220     GMACB_ReadPhy(pHw, phyAddress, GMII_ANER, &value, retryMax);
00221     TRACE_INFO(" _ANER     : 0x%X\n\r", (unsigned)value);
00222     GMACB_ReadPhy(pHw, phyAddress, GMII_ANNPR, &value, retryMax);
00223     TRACE_INFO(" _ANNPR    : 0x%X\n\r", (unsigned)value);
00224     GMACB_ReadPhy(pHw, phyAddress, GMII_ANLPNPAR, &value, retryMax);
00225     TRACE_INFO(" _ANLPNPAR : 0x%X\n\r", (unsigned)value);
00226 
00227     TRACE_INFO(" \n\r");
00228 
00229     GMACB_ReadPhy(pHw, phyAddress, GMII_RXERCR, &value, retryMax);
00230     TRACE_INFO(" _RXERCR   : 0x%X\n\r", (unsigned)value);
00231     GMACB_ReadPhy(pHw, phyAddress, GMII_ICSR, &value, retryMax);
00232     TRACE_INFO(" _ICSR     : 0x%X\n\r", (unsigned)value);
00233     TRACE_INFO(" \n\r");
00234 
00235     GMAC_DisableMdio(pHw);
00236 }
00237 
00238 /**
00239  * \brief Setup the maximum timeout count of the driver.
00240  * \param pMacb Pointer to the MACB instance
00241  * \param toMax Timeout maximum count.
00242  */
00243 void GMACB_SetupTimeout(GMacb *pMacb, uint32_t toMax)
00244 {
00245     pMacb->retryMax = toMax;
00246 }
00247 
00248 /**
00249  * \brief Initialize the MACB instance.
00250  * \param pMacb Pointer to the MACB instance
00251  * \param phyAddress   The PHY address used to access the PHY
00252  */
00253 void GMACB_Init(GMacb *pMacb, sGmacd *pGmacd, uint8_t phyAddress)
00254 {
00255     pMacb->pGmacd = pGmacd;
00256     pMacb->phyAddress = phyAddress;
00257     /* Initialize timeout by default */
00258     pMacb->retryMax = GMACB_RETRY_MAX;
00259 }
00260 
00261 
00262 /**
00263  * \brief Issue a SW reset to reset all registers of the PHY.
00264  * \param pMacb Pointer to the MACB instance
00265  * \return 1 if successfully, 0 if timeout.
00266  */
00267 uint8_t GMACB_ResetPhy(GMacb *pMacb)
00268 {
00269     sGmacd *pDrv = pMacb->pGmacd;
00270     Gmac *pHw = pDrv->pHw;
00271     uint32_t retryMax;
00272     uint32_t bmcr = GMII_RESET;
00273     uint8_t phyAddress;
00274     uint32_t timeout = 10;
00275     uint8_t ret = 1;
00276 
00277     TRACE_INFO(" GMACB_ResetPhy\n\r");
00278 
00279     phyAddress = pMacb->phyAddress;
00280     retryMax = pMacb->retryMax;
00281 
00282     GMAC_EnableMdio(pHw);
00283     bmcr = GMII_RESET;
00284     GMACB_WritePhy(pHw, phyAddress, GMII_BMCR, bmcr, retryMax);
00285 
00286     do {
00287         GMACB_ReadPhy(pHw, phyAddress, GMII_BMCR, &bmcr, retryMax);
00288         timeout--;
00289     } while ((bmcr & GMII_RESET) && timeout);
00290 
00291     GMAC_DisableMdio(pHw);
00292 
00293     if (!timeout) {
00294         ret = 0;
00295     }
00296 
00297     return( ret );
00298 }
00299 
00300 /**
00301  * \brief Do a HW initialize to the PHY ( via RSTC ) and set up clocks & PIOs
00302  * This should be called only once to initialize the PHY pre-settings.
00303  * The PHY address is reset status of CRS,RXD[3:0] (the emacPins' pullups).
00304  * The COL pin is used to select MII mode on reset (pulled up for Reduced MII)
00305  * The RXDV pin is used to select test mode on reset (pulled up for test mode)
00306  * The above pins should be predefined for corresponding settings in resetPins
00307  * The GMAC peripheral pins are configured after the reset done.
00308  * \param pMacb Pointer to the MACB instance
00309  * \param mck         Main clock setting to initialize clock
00310  * \param resetPins   Pointer to list of PIOs to configure before HW RESET
00311  *                       (for PHY power on reset configuration latch)
00312  * \param nbResetPins Number of PIO items that should be configured
00313  * \param emacPins    Pointer to list of PIOs for the EMAC interface
00314  * \param nbEmacPins  Number of PIO items that should be configured
00315  * \return 1 if RESET OK, 0 if timeout.
00316  */
00317 uint8_t GMACB_InitPhy(GMacb *pMacb,
00318         uint32_t mck,
00319         const Pin *pResetPins,
00320         uint32_t nbResetPins,
00321         const Pin *pGmacPins,
00322         uint32_t nbGmacPins)
00323 {
00324     sGmacd *pDrv = pMacb->pGmacd;
00325     Gmac *pHw = pDrv->pHw;
00326     uint8_t rc = 1;
00327     uint8_t phy;
00328 
00329     /* Perform RESET */
00330     TRACE_DEBUG("RESET PHY\n\r");
00331 
00332     if (pResetPins) {
00333         /* Configure PINS */
00334         PIO_Configure(pResetPins, nbResetPins);
00335         TRACE_INFO(" Hard Reset of GMACD Phy\n\r");
00336         PIO_Clear(pResetPins);
00337         Wait(100);
00338         PIO_Set(pResetPins);
00339     }
00340     /* Configure GMAC runtime pins */
00341     if (rc) {
00342 
00343         PIO_Configure(pGmacPins, nbGmacPins);
00344         rc = GMAC_SetMdcClock(pHw, mck );
00345         if (!rc) {
00346             TRACE_ERROR("No Valid MDC clock\n\r");
00347             return 0;
00348         }
00349 
00350         /* Check PHY Address */
00351         phy = GMACB_FindValidPhy(pMacb);
00352         if (phy == 0xFF) {
00353             TRACE_ERROR("PHY Access fail\n\r");
00354             return 0;
00355         }
00356         if(phy != pMacb->phyAddress) {
00357             pMacb->phyAddress = phy;
00358             GMACB_ResetPhy(pMacb);
00359         }
00360     }
00361     else {
00362         TRACE_ERROR("PHY Reset Timeout\n\r");
00363     }
00364     return rc;
00365 }
00366 
00367 /**
00368  * \brief Issue a Auto Negotiation of the PHY
00369  * \param pMacb Pointer to the MACB instance
00370  * \return 1 if successfully, 0 if timeout.
00371  */
00372 uint8_t GMACB_AutoNegotiate(GMacb *pMacb)
00373 {
00374     sGmacd *pDrv = pMacb->pGmacd;
00375     Gmac *pHw = pDrv->pHw;
00376     uint32_t retryMax;
00377     uint32_t value;
00378     uint32_t phyAnar;
00379     uint32_t phyAnalpar;
00380     uint32_t retryCount= 0;
00381     uint8_t phyAddress;
00382     uint8_t rc = 1;
00383     uint32_t duplex, speed;
00384     phyAddress = pMacb->phyAddress;
00385     retryMax = pMacb->retryMax;
00386 
00387     GMAC_EnableMdio(pHw);
00388 
00389     if (!GMACB_ReadPhy(pHw,phyAddress, GMII_PHYID1R, &value, retryMax)) {
00390         TRACE_ERROR("Pb GEMAC_ReadPhy Id1\n\r");
00391         rc = 0;
00392         goto AutoNegotiateExit;
00393     }
00394     TRACE_DEBUG("ReadPhy Id1 0x%X, address: %d\n\r", value, phyAddress);
00395     if (!GMACB_ReadPhy(pHw,phyAddress, GMII_PHYID2R, &phyAnar, retryMax)) {
00396         TRACE_ERROR("Pb GMACB_ReadPhy Id2\n\r");
00397         rc = 0;
00398         goto AutoNegotiateExit;
00399     }
00400     TRACE_DEBUG("ReadPhy Id2 0x%X\n\r", phyAnar);
00401 
00402     if( ( value == GMII_OUI_MSB )
00403             && ( ((phyAnar)&(~GMII_LSB_MASK)) == GMII_OUI_LSB ) ) {
00404         TRACE_DEBUG("Vendor Number Model = 0x%X\n\r", ((phyAnar>>4)&0x3F));
00405         TRACE_DEBUG("Model Revision Number = 0x%X\n\r", (phyAnar&0xF));
00406     } else {
00407         TRACE_ERROR("Problem OUI value\n\r");
00408     }
00409 
00410     /** Set the Auto_negotiation Advertisement Register, MII advertising for 
00411     Next page 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 */
00412     rc  = GMACB_ReadPhy(pHw, phyAddress, GMII_ANAR, &phyAnar, retryMax);
00413     if (rc == 0) {
00414         goto AutoNegotiateExit;
00415     }
00416     phyAnar = GMII_TX_FDX | GMII_TX_HDX |
00417         GMII_10_FDX | GMII_10_HDX | GMII_AN_IEEE_802_3;
00418     rc = GMACB_WritePhy(pHw,phyAddress, GMII_ANAR, phyAnar, retryMax);
00419     if (rc == 0) {
00420         goto AutoNegotiateExit;
00421     }
00422 
00423     /* Read & modify control register */
00424     rc  = GMACB_ReadPhy(pHw, phyAddress, GMII_BMCR, &value, retryMax);
00425     if (rc == 0) {
00426         goto AutoNegotiateExit;
00427     }
00428 
00429     /* Check AutoNegotiate complete */
00430     value |=  GMII_AUTONEG | GMII_RESTART_AUTONEG;
00431     rc = GMACB_WritePhy(pHw, phyAddress, GMII_BMCR, value, retryMax);
00432     if (rc == 0) {
00433         goto AutoNegotiateExit;
00434     }
00435     TRACE_DEBUG(" _BMCR: 0x%X\n\r", value);
00436 
00437     // Check AutoNegotiate complete
00438     while (1) {
00439         rc  = GMACB_ReadPhy(pHw, phyAddress, GMII_BMSR, &value, retryMax);
00440         if (rc == 0) {
00441             TRACE_ERROR("rc==0\n\r");
00442             goto AutoNegotiateExit;
00443         }
00444         /* Done successfully */
00445         if (value & GMII_AUTONEG_COMP) {
00446             printf("AutoNegotiate complete\n\r");
00447             break;
00448         }
00449         /* Timeout check */
00450         if (retryMax) {
00451             if (++ retryCount >= retryMax) {
00452                 GMACB_DumpRegisters(pMacb);
00453                 TRACE_ERROR("TimeOut\n\r");
00454                 rc = 0;
00455                 goto AutoNegotiateExit; 
00456             }
00457         }
00458     }
00459 
00460     /*Set local link mode */
00461     while(1) {
00462         rc  = GMACB_ReadPhy(pHw, phyAddress, GMII_ANLPAR, &phyAnalpar, retryMax);
00463         if (rc == 0) {
00464             goto AutoNegotiateExit;
00465         }
00466         /* Set up the GMAC link speed */
00467         if ((phyAnar & phyAnalpar) & GMII_TX_FDX) {
00468             /* set RGMII for 1000BaseTX and Full Duplex */
00469             duplex = GMAC_DUPLEX_FULL;
00470             speed = GMAC_SPEED_100M;
00471             break;
00472         } else if ((phyAnar & phyAnalpar) & GMII_10_FDX) {
00473             /* set RGMII for 1000BaseT and Half Duplex*/
00474             duplex = GMAC_DUPLEX_FULL;
00475             speed = GMAC_SPEED_10M;
00476             break;
00477         } else if ((phyAnar & phyAnalpar) & GMII_TX_HDX) {
00478             /* set RGMII for 100BaseTX and half Duplex */
00479             duplex = GMAC_DUPLEX_HALF;
00480             speed = GMAC_SPEED_100M;
00481             break;
00482         } else if ((phyAnar & phyAnalpar) & GMII_10_HDX) {
00483             // set RGMII for 10BaseT and half Duplex
00484             duplex = GMAC_DUPLEX_HALF;
00485             speed = GMAC_SPEED_10M;
00486             break;
00487         }
00488     }
00489     TRACE_INFO("GMAC_EnableRGMII duplex %u, speed %u\n\r",(unsigned)duplex,(unsigned)speed);
00490 
00491     GMACB_ReadPhy(pHw,phyAddress, GMII_PC1R, &value, retryMax);
00492     GMACB_ReadPhy(pHw,phyAddress, GMII_PC2R, &value, retryMax);
00493     GMACB_ReadPhy(pHw,phyAddress, GMII_ICSR, &value, retryMax);
00494     /* Set up GMAC mode  */
00495     GMAC_EnableRGMII(pHw, duplex, speed);
00496 
00497 AutoNegotiateExit:
00498     GMAC_DisableMdio(pHw);
00499     return rc;
00500 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines