1 /* ----------------------------------------------------------------------------
\r
2 * SAM Software Package License
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2014, Atmel Corporation
\r
6 * All rights reserved.
\r
8 * Redistribution and use in source and binary forms, with or without
\r
9 * modification, are permitted provided that the following conditions are met:
\r
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\r
14 * Atmel's name may not be used to endorse or promote products derived from
\r
15 * this software without specific prior written permission.
\r
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
\r
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
\r
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
27 * ----------------------------------------------------------------------------
\r
32 /*----------------------------------------------------------------------------
\r
34 *----------------------------------------------------------------------------*/
\r
43 /*----------------------------------------------------------------------------
\r
44 * Internal functions
\r
45 *----------------------------------------------------------------------------*/
\r
46 /*----------------------------------------------------------------------------
\r
47 * Exported functions
\r
48 *----------------------------------------------------------------------------*/
\r
51 * Return 1 if PHY is idle
\r
53 uint8_t GMAC_IsIdle(Gmac *pGmac)
\r
55 return ((pGmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);
\r
60 * Execute PHY maintanance command
\r
62 void GMAC_PHYMaintain(Gmac *pGmac,
\r
68 /* Wait until bus idle */
\r
69 while((pGmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
\r
70 /* Write maintain register */
\r
71 pGmac->GMAC_MAN = (~GMAC_MAN_WZO & GMAC_MAN_CLTTO)
\r
72 | (GMAC_MAN_OP(bRW ? 0x2 : 0x1))
\r
73 | GMAC_MAN_WTN(0x02)
\r
74 | GMAC_MAN_PHYA(bPhyAddr)
\r
75 | GMAC_MAN_REGA(bRegAddr)
\r
76 | GMAC_MAN_DATA(wData) ;
\r
80 * Return PHY maintainance data returned
\r
82 uint16_t GMAC_PHYData(Gmac *pGmac)
\r
84 /* Wait until bus idle */
\r
85 while((pGmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);
\r
87 return (uint16_t)(pGmac->GMAC_MAN & GMAC_MAN_DATA_Msk);
\r
91 * \brief Set MDC clock according to current board clock. Per 802.3, MDC should be
\r
93 * \param pGmac Pointer to an Gmac instance.
\r
94 * \param mck Mdc clock
\r
95 * \return 1 if successfully, 0 if MDC clock not found.
\r
97 uint8_t GMAC_SetMdcClock( Gmac *pGmac, uint32_t mck )
\r
99 uint32_t clock_dividor;
\r
100 pGmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
101 if (mck <= 20000000) {
\r
102 clock_dividor = GMAC_NCFGR_CLK_MCK_8; // MDC clock = MCK/8
\r
104 else if (mck <= 40000000) {
\r
105 clock_dividor = GMAC_NCFGR_CLK_MCK_16; // MDC clock = MCK/16
\r
107 else if (mck <= 80000000) {
\r
108 clock_dividor = GMAC_NCFGR_CLK_MCK_32; // MDC clock = MCK/32
\r
110 else if (mck <= 160000000) {
\r
111 clock_dividor = GMAC_NCFGR_CLK_MCK_64; // MDC clock = MCK/64
\r
113 else if (mck <= 240000000) {
\r
114 clock_dividor = GMAC_NCFGR_CLK_MCK_96; // MDC clock = MCK/96
\r
117 TRACE_ERROR("E: No valid MDC clock.\n\r");
\r
120 pGmac->GMAC_NCFGR = (pGmac->GMAC_NCFGR & (~GMAC_NCFGR_CLK_Msk)) | clock_dividor;
\r
121 pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
126 * \brief Enable MDI with PHY
\r
127 * \param pGmac Pointer to an Gmac instance.
\r
129 void GMAC_EnableMdio( Gmac *pGmac )
\r
131 pGmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
132 pGmac->GMAC_NCR |= GMAC_NCR_MPE;
\r
133 pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
137 * \brief Enable MDI with PHY
\r
138 * \param pGmac Pointer to an Gmac instance.
\r
140 void GMAC_DisableMdio( Gmac *pGmac )
\r
142 pGmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
143 pGmac->GMAC_NCR &= ~GMAC_NCR_MPE;
\r
144 pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
148 * \brief Enable MII mode for GMAC, called once after autonegotiate
\r
149 * \param pGmac Pointer to an Gmac instance.
\r
151 void GMAC_EnableMII( Gmac *pGmac )
\r
153 pGmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
154 pGmac->GMAC_UR &= ~GMAC_UR_RMIIMII;
\r
155 pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
159 * \brief Enable GMII mode for GMAC, called once after autonegotiate
\r
160 * \param pGmac Pointer to an Gmac instance.
\r
162 void GMAC_EnableGMII( Gmac *pGmac )
\r
164 pGmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
165 /* RGMII disable */
\r
166 pGmac->GMAC_UR &= ~GMAC_UR_RMIIMII;
\r
167 pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
170 #define GMAC_NCFGR_GBE (0x1u << 10)
\r
172 * \brief Enable RGMII mode for GMAC, called once after autonegotiate
\r
173 * \param pGmac Pointer to an Gmac instance.
\r
174 * \param duplex: 1 full duplex 0 half duplex
\r
175 * \param speed: 0 10M 1 100M
\r
177 void GMAC_EnableRGMII(Gmac *pGmac, uint32_t duplex, uint32_t speed)
\r
179 pGmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
180 if (duplex == GMAC_DUPLEX_HALF)
\r
182 pGmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;
\r
186 pGmac->GMAC_NCFGR |= GMAC_NCFGR_FD;
\r
190 if (speed == GMAC_SPEED_10M)
\r
192 pGmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;
\r
194 else if(speed == GMAC_SPEED_100M)
\r
196 pGmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;
\r
200 pGmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;
\r
204 pGmac->GMAC_UR = 0;
\r
205 pGmac->GMAC_NCFGR &= ~GMAC_NCFGR_GBE;
\r
206 pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
211 * \brief Setup the GMAC for the link : speed 100M/10M and Full/Half duplex
\r
212 * \param pGmac Pointer to an Gmac instance.
\r
213 * \param speed Link speed, 0 for 10M, 1 for 100M
\r
214 * \param fullduplex 1 for Full Duplex mode
\r
216 void GMAC_SetLinkSpeed(Gmac *pGmac, uint8_t speed, uint8_t fullduplex)
\r
219 ncfgr = pGmac->GMAC_NCFGR;
\r
220 ncfgr &= ~(GMAC_NCFGR_SPD | GMAC_NCFGR_FD);
\r
223 ncfgr |= GMAC_NCFGR_SPD;
\r
227 ncfgr |= GMAC_NCFGR_FD;
\r
229 pGmac->GMAC_NCFGR = ncfgr;
\r
230 pGmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
\r
234 * \brief set local loop back
\r
235 * \param pGmac Pointer to an Gmac instance.
\r
237 uint32_t GMAC_SetLocalLoopBack(Gmac *pGmac)
\r
239 pGmac->GMAC_NCR |= GMAC_NCR_LBL;
\r
244 * Return interrupt mask.
\r
246 uint32_t GMAC_GetItMask(Gmac *pGmac, gmacQueList_t queueIdx)
\r
251 return pGmac->GMAC_IMR;
\r
255 return pGmac->GMAC_IMRPQ[queueIdx -1];
\r
261 * Return transmit status
\r
263 uint32_t GMAC_GetTxStatus(Gmac *pGmac)
\r
265 return pGmac->GMAC_TSR;
\r
269 * Clear transmit status
\r
271 void GMAC_ClearTxStatus(Gmac *pGmac, uint32_t dwStatus)
\r
273 pGmac->GMAC_TSR = dwStatus;
\r
277 * Return receive status
\r
279 uint32_t GMAC_GetRxStatus(Gmac *pGmac)
\r
281 return pGmac->GMAC_RSR;
\r
285 * Clear receive status
\r
287 void GMAC_ClearRxStatus(Gmac *pGmac, uint32_t dwStatus)
\r
289 pGmac->GMAC_RSR = dwStatus;
\r
294 * Enable/Disable GMAC receive.
\r
296 void GMAC_ReceiveEnable(Gmac* pGmac, uint8_t bEnaDis)
\r
298 if (bEnaDis) pGmac->GMAC_NCR |= GMAC_NCR_RXEN;
\r
299 else pGmac->GMAC_NCR &= ~GMAC_NCR_RXEN;
\r
303 * Enable/Disable GMAC transmit.
\r
305 void GMAC_TransmitEnable(Gmac *pGmac, uint8_t bEnaDis)
\r
307 if (bEnaDis) pGmac->GMAC_NCR |= GMAC_NCR_TXEN;
\r
308 else pGmac->GMAC_NCR &= ~GMAC_NCR_TXEN;
\r
315 void GMAC_SetRxQueue(Gmac *pGmac, uint32_t dwAddr, gmacQueList_t queueIdx)
\r
319 pGmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & dwAddr;
\r
323 pGmac->GMAC_RBQBAPQ[queueIdx - 1] = GMAC_RBQB_ADDR_Msk & dwAddr;
\r
328 * Get Rx Queue Address
\r
330 uint32_t GMAC_GetRxQueue(Gmac *pGmac, gmacQueList_t queueIdx)
\r
334 return pGmac->GMAC_RBQB;
\r
338 return pGmac->GMAC_RBQBAPQ[queueIdx - 1];
\r
345 void GMAC_SetTxQueue(Gmac *pGmac, uint32_t dwAddr, gmacQueList_t queueIdx)
\r
349 pGmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & dwAddr;
\r
353 pGmac->GMAC_TBQBAPQ[queueIdx - 1] = GMAC_TBQB_ADDR_Msk & dwAddr;
\r
361 uint32_t GMAC_GetTxQueue(Gmac *pGmac, gmacQueList_t queueIdx)
\r
366 return pGmac->GMAC_TBQB;
\r
371 return pGmac->GMAC_TBQBAPQ[queueIdx - 1];
\r
378 * Write control value
\r
380 void GMAC_NetworkControl(Gmac *pGmac, uint32_t bmNCR)
\r
382 pGmac->GMAC_NCR = bmNCR;
\r
387 * Get control value
\r
389 uint32_t GMAC_GetNetworkControl(Gmac *pGmac)
\r
391 return pGmac->GMAC_NCR;
\r
396 * Enable interrupt(s).
\r
398 void GMAC_EnableIt(Gmac *pGmac, uint32_t dwSources, gmacQueList_t queueIdx)
\r
402 pGmac->GMAC_IER = dwSources;
\r
406 pGmac->GMAC_IERPQ[queueIdx-1] = dwSources;
\r
411 * Disable interrupt(s).
\r
413 void GMAC_DisableAllQueueIt(Gmac *pGmac, uint32_t dwSources)
\r
415 pGmac->GMAC_IDR = dwSources;
\r
416 pGmac->GMAC_IDRPQ[0] = dwSources;
\r
417 pGmac->GMAC_IDRPQ[1] = dwSources;
\r
421 * Disable interrupt(s).
\r
423 void GMAC_EnableAllQueueIt(Gmac *pGmac, uint32_t dwSources)
\r
425 pGmac->GMAC_IER = dwSources;
\r
426 pGmac->GMAC_IERPQ[0] = dwSources;
\r
427 pGmac->GMAC_IERPQ[1] = dwSources;
\r
431 * Disable interrupt(s).
\r
433 void GMAC_DisableIt(Gmac *pGmac, uint32_t dwSources, gmacQueList_t queueIdx)
\r
438 pGmac->GMAC_IDR = dwSources;
\r
442 pGmac->GMAC_IDRPQ[queueIdx-1] = dwSources;
\r
447 * Return interrupt status.
\r
449 uint32_t GMAC_GetItStatus(Gmac *pGmac, gmacQueList_t queueIdx)
\r
453 return pGmac->GMAC_ISR;
\r
457 return pGmac->GMAC_ISRPQ[queueIdx-1];
\r
465 void GMAC_SetAddress(Gmac *pGmac, uint8_t bIndex, uint8_t *pMacAddr)
\r
468 pGmac->GMAC_SA[bIndex].GMAC_SAB = (pMacAddr[3] << 24)
\r
469 | (pMacAddr[2] << 16)
\r
470 | (pMacAddr[1] << 8)
\r
473 pGmac->GMAC_SA[bIndex].GMAC_SAT = (pMacAddr[5] << 8)
\r
479 * Set MAC Address via 2 DW
\r
481 void GMAC_SetAddress32(Gmac *pGmac, uint8_t bIndex, uint32_t dwMacT, uint32_t dwMacB)
\r
483 pGmac->GMAC_SA[bIndex].GMAC_SAB = dwMacB;
\r
484 pGmac->GMAC_SA[bIndex].GMAC_SAT = dwMacT;
\r
488 * Set MAC Address via int64
\r
490 void GMAC_SetAddress64(Gmac *pGmac, uint8_t bIndex, uint64_t ddwMac)
\r
492 pGmac->GMAC_SA[bIndex].GMAC_SAB = (uint32_t)ddwMac;
\r
493 pGmac->GMAC_SA[bIndex].GMAC_SAT = (uint32_t)(ddwMac >> 32);
\r
498 * Clear all statistics registers
\r
500 void GMAC_ClearStatistics(Gmac *pGmac)
\r
502 pGmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;
\r
506 * Increase all statistics registers
\r
508 void GMAC_IncreaseStatistics(Gmac *pGmac)
\r
510 pGmac->GMAC_NCR |= GMAC_NCR_INCSTAT;
\r
514 * Enable/Disable statistics registers writing.
\r
516 void GMAC_StatisticsWriteEnable(Gmac *pGmac, uint8_t bEnaDis)
\r
518 if (bEnaDis) pGmac->GMAC_NCR |= GMAC_NCR_WESTAT;
\r
519 else pGmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;
\r
524 * Setup network configuration register
\r
526 void GMAC_Configure(Gmac *pGmac, uint32_t dwCfg)
\r
528 pGmac->GMAC_NCFGR = dwCfg;
\r
532 * Setup network configuration register
\r
534 void GMAC_DmaConfigure(Gmac *pGmac, uint32_t dwCfg)
\r
536 pGmac->GMAC_DCFGR = dwCfg;
\r
540 * Return network configuration.
\r
542 uint32_t GMAC_GetConfigure(Gmac *pGmac)
\r
544 return pGmac->GMAC_NCFGR;
\r
549 * Start transmission
\r
551 void GMAC_TransmissionStart(Gmac *pGmac)
\r
553 pGmac->GMAC_NCR |= GMAC_NCR_TSTART;
\r
557 * Halt transmission
\r
559 void GMAC_TransmissionHalt(Gmac *pGmac)
\r
561 pGmac->GMAC_NCR |= GMAC_NCR_THALT;
\r