SAMV71 Xplained Ultra Software Package 1.5

gmacb_phy.c

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