]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained_IAR_Keil/libchip_samv7/source/gmac.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained_IAR_Keil / libchip_samv7 / source / gmac.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License \r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2014, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\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
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\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
16  *\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
28  */\r
29 \r
30 /** \file */\r
31 \r
32 /*----------------------------------------------------------------------------\r
33  *        Headers\r
34  *----------------------------------------------------------------------------*/\r
35 \r
36 #include "chip.h"\r
37 #include <stdio.h>\r
38 #include <string.h>\r
39 #include <assert.h>\r
40 \r
41 \r
42 \r
43 /*----------------------------------------------------------------------------\r
44  *        Internal functions\r
45  *----------------------------------------------------------------------------*/\r
46 /*----------------------------------------------------------------------------\r
47  *        Exported functions\r
48  *----------------------------------------------------------------------------*/\r
49 \r
50 /**\r
51  * Return 1 if PHY is idle\r
52  */\r
53 uint8_t GMAC_IsIdle(Gmac *pGmac)\r
54 {\r
55     return ((pGmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);\r
56 }\r
57 \r
58 \r
59 /**\r
60  * Execute PHY maintanance command\r
61  */\r
62 void GMAC_PHYMaintain(Gmac      *pGmac,\r
63         uint8_t   bPhyAddr,\r
64         uint8_t   bRegAddr,\r
65         uint8_t   bRW,\r
66         uint16_t  wData)\r
67 {\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
77 }\r
78 \r
79 /**\r
80  * Return PHY maintainance data returned\r
81  */\r
82 uint16_t GMAC_PHYData(Gmac *pGmac)\r
83 {\r
84     /* Wait until bus idle */\r
85     while((pGmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
86     /* Return data */\r
87     return (uint16_t)(pGmac->GMAC_MAN & GMAC_MAN_DATA_Msk);\r
88 }\r
89 \r
90 /**\r
91  *  \brief Set MDC clock according to current board clock. Per 802.3, MDC should be \r
92  *  less then 2.5MHz.\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
96  */\r
97 uint8_t GMAC_SetMdcClock( Gmac *pGmac, uint32_t mck )\r
98 {\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
103     }\r
104     else if (mck <= 40000000) {\r
105         clock_dividor = GMAC_NCFGR_CLK_MCK_16;         // MDC clock = MCK/16\r
106     }\r
107     else if (mck <= 80000000) {\r
108         clock_dividor = GMAC_NCFGR_CLK_MCK_32;         // MDC clock = MCK/32\r
109     }\r
110     else if (mck <= 160000000) {\r
111         clock_dividor = GMAC_NCFGR_CLK_MCK_64;         // MDC clock = MCK/64\r
112     }\r
113     else if (mck <= 240000000) {\r
114         clock_dividor = GMAC_NCFGR_CLK_MCK_96;         // MDC clock = MCK/96\r
115     }\r
116     else {\r
117         TRACE_ERROR("E: No valid MDC clock.\n\r");\r
118         return 0;\r
119     }\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
122     return 1;\r
123 }\r
124 \r
125 /**\r
126  *  \brief Enable MDI with PHY\r
127  *  \param pGmac Pointer to an Gmac instance.\r
128  */\r
129 void GMAC_EnableMdio( Gmac *pGmac )\r
130 {\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
134 }\r
135 \r
136 /**\r
137  *  \brief Enable MDI with PHY\r
138  *  \param pGmac Pointer to an Gmac instance.\r
139  */\r
140 void GMAC_DisableMdio( Gmac *pGmac )\r
141 {\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
145 }\r
146 \r
147 /**\r
148  *  \brief Enable MII mode for GMAC, called once after autonegotiate\r
149  *  \param pGmac Pointer to an Gmac instance.\r
150  */\r
151 void GMAC_EnableMII( Gmac *pGmac )\r
152 {\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
156 }\r
157 \r
158 /**\r
159  *  \brief Enable GMII mode for GMAC, called once after autonegotiate\r
160  *  \param pGmac Pointer to an Gmac instance.\r
161  */\r
162 void GMAC_EnableGMII( Gmac *pGmac )\r
163 {\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
168 }\r
169 \r
170 #define GMAC_NCFGR_GBE (0x1u << 10)\r
171 /**\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
176  */\r
177 void GMAC_EnableRGMII(Gmac *pGmac, uint32_t duplex, uint32_t speed)\r
178 {\r
179     pGmac->GMAC_NCR &=  ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);\r
180     if (duplex == GMAC_DUPLEX_HALF)\r
181     {\r
182         pGmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;\r
183     }\r
184     else \r
185     {\r
186         pGmac->GMAC_NCFGR |= GMAC_NCFGR_FD;\r
187     }\r
188 \r
189 \r
190     if (speed == GMAC_SPEED_10M)\r
191     {\r
192         pGmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;\r
193     }\r
194     else if(speed == GMAC_SPEED_100M) \r
195     {\r
196         pGmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;\r
197     }\r
198     else\r
199     {\r
200         pGmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;\r
201     }\r
202 \r
203     /* RGMII enable */\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
207     return;\r
208 }\r
209 \r
210 /**\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
215  */\r
216 void GMAC_SetLinkSpeed(Gmac *pGmac, uint8_t speed, uint8_t fullduplex)\r
217 {\r
218     uint32_t ncfgr;\r
219     ncfgr = pGmac->GMAC_NCFGR;\r
220     ncfgr &= ~(GMAC_NCFGR_SPD | GMAC_NCFGR_FD);\r
221     if (speed) {\r
222 \r
223         ncfgr |= GMAC_NCFGR_SPD;\r
224     }\r
225     if (fullduplex) {\r
226 \r
227         ncfgr |= GMAC_NCFGR_FD;\r
228     }\r
229     pGmac->GMAC_NCFGR = ncfgr;\r
230     pGmac->GMAC_NCR |=  (GMAC_NCR_RXEN | GMAC_NCR_TXEN);\r
231 }\r
232 \r
233 /**\r
234  *  \brief set local loop back\r
235  *  \param pGmac Pointer to an Gmac instance.\r
236  */\r
237 uint32_t GMAC_SetLocalLoopBack(Gmac *pGmac)\r
238 {\r
239     pGmac->GMAC_NCR |= GMAC_NCR_LBL;\r
240     return 0;\r
241 }\r
242 \r
243 /**\r
244  * Return interrupt mask.\r
245  */\r
246 uint32_t GMAC_GetItMask(Gmac *pGmac, gmacQueList_t queueIdx)\r
247 {\r
248 \r
249     if(!queueIdx)\r
250     {\r
251         return pGmac->GMAC_IMR;\r
252     }\r
253     else\r
254     {\r
255         return pGmac->GMAC_IMRPQ[queueIdx -1];\r
256     }\r
257 }\r
258 \r
259 \r
260 /**\r
261  * Return transmit status\r
262  */\r
263 uint32_t GMAC_GetTxStatus(Gmac *pGmac)\r
264 {\r
265     return pGmac->GMAC_TSR;    \r
266 }\r
267 \r
268 /**\r
269  * Clear transmit status\r
270  */\r
271 void GMAC_ClearTxStatus(Gmac *pGmac, uint32_t dwStatus)\r
272 {\r
273     pGmac->GMAC_TSR = dwStatus;\r
274 }\r
275 \r
276 /**\r
277  * Return receive status\r
278  */\r
279 uint32_t GMAC_GetRxStatus(Gmac *pGmac)\r
280 {\r
281     return pGmac->GMAC_RSR;\r
282 }\r
283 \r
284 /**\r
285  * Clear receive status\r
286  */\r
287 void GMAC_ClearRxStatus(Gmac *pGmac, uint32_t dwStatus)\r
288 {\r
289     pGmac->GMAC_RSR = dwStatus;\r
290 }\r
291 \r
292 \r
293 /**\r
294  * Enable/Disable GMAC receive.\r
295  */\r
296 void GMAC_ReceiveEnable(Gmac* pGmac, uint8_t bEnaDis)\r
297 {\r
298     if (bEnaDis) pGmac->GMAC_NCR |=  GMAC_NCR_RXEN;\r
299     else         pGmac->GMAC_NCR &= ~GMAC_NCR_RXEN;\r
300 }\r
301 \r
302 /**\r
303  * Enable/Disable GMAC transmit.\r
304  */\r
305 void GMAC_TransmitEnable(Gmac *pGmac, uint8_t bEnaDis)\r
306 {\r
307     if (bEnaDis) pGmac->GMAC_NCR |=  GMAC_NCR_TXEN;\r
308     else         pGmac->GMAC_NCR &= ~GMAC_NCR_TXEN;\r
309 }\r
310 \r
311 \r
312 /**\r
313  * Set Rx Queue\r
314  */\r
315 void GMAC_SetRxQueue(Gmac *pGmac, uint32_t dwAddr, gmacQueList_t queueIdx)\r
316 {\r
317     if(!queueIdx)\r
318     {\r
319         pGmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & dwAddr;\r
320     }\r
321     else\r
322     {\r
323         pGmac->GMAC_RBQBAPQ[queueIdx - 1] = GMAC_RBQB_ADDR_Msk & dwAddr;\r
324     }\r
325 }\r
326 \r
327 /**\r
328  * Get Rx Queue Address\r
329  */\r
330 uint32_t GMAC_GetRxQueue(Gmac *pGmac, gmacQueList_t queueIdx)\r
331 {\r
332     if(!queueIdx)\r
333     {\r
334         return pGmac->GMAC_RBQB;\r
335     }\r
336     else\r
337     {\r
338         return pGmac->GMAC_RBQBAPQ[queueIdx - 1];\r
339     }    \r
340 }\r
341 \r
342 /**\r
343  * Set Tx Queue\r
344  */\r
345 void GMAC_SetTxQueue(Gmac *pGmac, uint32_t dwAddr, gmacQueList_t queueIdx)\r
346 {\r
347     if(!queueIdx)\r
348     {\r
349         pGmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & dwAddr;\r
350     }\r
351     else\r
352     {\r
353         pGmac->GMAC_TBQBAPQ[queueIdx - 1] = GMAC_TBQB_ADDR_Msk & dwAddr;\r
354     }\r
355 \r
356 }\r
357 \r
358 /**\r
359  * Get Tx Queue\r
360  */\r
361 uint32_t GMAC_GetTxQueue(Gmac *pGmac, gmacQueList_t queueIdx)\r
362 {\r
363 \r
364     if(!queueIdx)\r
365     {\r
366         return pGmac->GMAC_TBQB;\r
367 \r
368     }\r
369     else\r
370     {\r
371         return pGmac->GMAC_TBQBAPQ[queueIdx - 1];\r
372     }\r
373 \r
374 }\r
375 \r
376 \r
377 /**\r
378  * Write control value\r
379  */\r
380 void GMAC_NetworkControl(Gmac *pGmac, uint32_t bmNCR)\r
381 {\r
382     pGmac->GMAC_NCR = bmNCR;\r
383 }\r
384 \r
385 \r
386 /**\r
387  * Get control value\r
388  */\r
389 uint32_t GMAC_GetNetworkControl(Gmac *pGmac)\r
390 {\r
391     return pGmac->GMAC_NCR;\r
392 }\r
393 \r
394 \r
395 /**\r
396  * Enable interrupt(s).\r
397  */\r
398 void GMAC_EnableIt(Gmac *pGmac, uint32_t dwSources, gmacQueList_t queueIdx)\r
399 {\r
400     if(!queueIdx)\r
401     {\r
402         pGmac->GMAC_IER = dwSources;\r
403     }\r
404     else\r
405     {\r
406         pGmac->GMAC_IERPQ[queueIdx-1] = dwSources;\r
407     }\r
408 }\r
409 \r
410 /**\r
411  * Disable interrupt(s).\r
412  */\r
413 void GMAC_DisableAllQueueIt(Gmac *pGmac, uint32_t dwSources)\r
414 {\r
415     pGmac->GMAC_IDR = dwSources;\r
416     pGmac->GMAC_IDRPQ[0] = dwSources;\r
417     pGmac->GMAC_IDRPQ[1] = dwSources;\r
418 }\r
419 \r
420 /**\r
421  * Disable interrupt(s).\r
422  */\r
423 void GMAC_EnableAllQueueIt(Gmac *pGmac, uint32_t dwSources)\r
424 {\r
425     pGmac->GMAC_IER = dwSources;\r
426     pGmac->GMAC_IERPQ[0] = dwSources;\r
427     pGmac->GMAC_IERPQ[1] = dwSources;\r
428 }\r
429 \r
430 /**\r
431  * Disable interrupt(s).\r
432  */\r
433 void GMAC_DisableIt(Gmac *pGmac, uint32_t dwSources, gmacQueList_t queueIdx)\r
434 {\r
435 \r
436     if(!queueIdx)\r
437     {\r
438         pGmac->GMAC_IDR = dwSources;\r
439     }\r
440     else\r
441     {\r
442         pGmac->GMAC_IDRPQ[queueIdx-1] = dwSources;\r
443     }\r
444 }\r
445 \r
446 /**\r
447  * Return interrupt status.\r
448  */\r
449 uint32_t GMAC_GetItStatus(Gmac *pGmac, gmacQueList_t queueIdx)\r
450 {    \r
451     if(!queueIdx)\r
452     {\r
453         return pGmac->GMAC_ISR;\r
454     }\r
455     else\r
456     {\r
457         return pGmac->GMAC_ISRPQ[queueIdx-1];\r
458     }\r
459 }\r
460 \r
461 \r
462 /**\r
463  * Set MAC Address\r
464  */\r
465 void GMAC_SetAddress(Gmac *pGmac, uint8_t bIndex, uint8_t *pMacAddr)\r
466 {\r
467 \r
468     pGmac->GMAC_SA[bIndex].GMAC_SAB = (pMacAddr[3] << 24)\r
469         | (pMacAddr[2] << 16)\r
470         | (pMacAddr[1] <<  8)\r
471         | (pMacAddr[0]      )\r
472         ;\r
473     pGmac->GMAC_SA[bIndex].GMAC_SAT = (pMacAddr[5] <<  8)\r
474         | (pMacAddr[4]      )\r
475         ;\r
476 }\r
477 \r
478 /**\r
479  * Set MAC Address via 2 DW\r
480  */\r
481 void GMAC_SetAddress32(Gmac *pGmac, uint8_t bIndex, uint32_t dwMacT, uint32_t dwMacB)\r
482 {\r
483     pGmac->GMAC_SA[bIndex].GMAC_SAB = dwMacB;\r
484     pGmac->GMAC_SA[bIndex].GMAC_SAT = dwMacT;\r
485 }\r
486 \r
487 /**\r
488  * Set MAC Address via int64\r
489  */\r
490 void GMAC_SetAddress64(Gmac *pGmac, uint8_t bIndex, uint64_t ddwMac)\r
491 {\r
492     pGmac->GMAC_SA[bIndex].GMAC_SAB = (uint32_t)ddwMac;\r
493     pGmac->GMAC_SA[bIndex].GMAC_SAT = (uint32_t)(ddwMac >> 32);\r
494 }\r
495 \r
496 \r
497 /**\r
498  * Clear all statistics registers\r
499  */\r
500 void GMAC_ClearStatistics(Gmac *pGmac)\r
501 {\r
502     pGmac->GMAC_NCR |=  GMAC_NCR_CLRSTAT;\r
503 }\r
504 \r
505 /**\r
506  * Increase all statistics registers\r
507  */\r
508 void GMAC_IncreaseStatistics(Gmac *pGmac)\r
509 {\r
510     pGmac->GMAC_NCR |=  GMAC_NCR_INCSTAT;\r
511 }\r
512 \r
513 /**\r
514  * Enable/Disable statistics registers writing.\r
515  */\r
516 void GMAC_StatisticsWriteEnable(Gmac *pGmac, uint8_t bEnaDis)\r
517 {\r
518     if (bEnaDis) pGmac->GMAC_NCR |=  GMAC_NCR_WESTAT;\r
519     else         pGmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;\r
520 }\r
521 \r
522 \r
523 /**\r
524  * Setup network configuration register\r
525  */\r
526 void GMAC_Configure(Gmac *pGmac, uint32_t dwCfg)\r
527 {\r
528     pGmac->GMAC_NCFGR = dwCfg;\r
529 }\r
530 \r
531 /**\r
532  * Setup network configuration register\r
533  */\r
534 void GMAC_DmaConfigure(Gmac *pGmac, uint32_t dwCfg)\r
535 {\r
536     pGmac->GMAC_DCFGR = dwCfg;\r
537 }\r
538 \r
539 /**\r
540  * Return network configuration.\r
541  */\r
542 uint32_t GMAC_GetConfigure(Gmac *pGmac)\r
543 {\r
544     return pGmac->GMAC_NCFGR;\r
545 }\r
546 \r
547 \r
548 /**\r
549  * Start transmission\r
550  */\r
551 void GMAC_TransmissionStart(Gmac *pGmac)\r
552 {\r
553     pGmac->GMAC_NCR |= GMAC_NCR_TSTART;\r
554 }\r
555 \r
556 /**\r
557  * Halt transmission\r
558  */\r
559 void GMAC_TransmissionHalt(Gmac *pGmac)\r
560 {\r
561     pGmac->GMAC_NCR |= GMAC_NCR_THALT;\r
562 }\r