sc598_eth1_driver.c
Go to the documentation of this file.
1 /**
2  * @file sc598_eth1_driver.c
3  * @brief ADSP-SC598 Ethernet MAC driver (EMAC0 instance)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include <sys/platform.h>
36 #include <services/int/adi_int.h>
37 #include "core/net.h"
39 #include "debug.h"
40 
41 //Underlying network interface
42 static NetInterface *nicDriverInterface;
43 
44 //IAR EWARM compiler?
45 #if defined(__ICCARM__)
46 
47 //Transmit buffer
48 #pragma data_alignment = 4
49 #pragma location = SC598_ETH1_RAM_SECTION
51 //Receive buffer
52 #pragma data_alignment = 4
53 #pragma location = SC598_ETH1_RAM_SECTION
55 //Transmit DMA descriptors
56 #pragma data_alignment = 8
57 #pragma location = SC598_ETH1_RAM_SECTION
59 //Receive DMA descriptors
60 #pragma data_alignment = 8
61 #pragma location = SC598_ETH1_RAM_SECTION
63 
64 //GCC compiler?
65 #else
66 
67 //Transmit buffer
69  __attribute__((aligned(4), __section__(SC598_ETH1_RAM_SECTION)));
70 //Receive buffer
72  __attribute__((aligned(4), __section__(SC598_ETH1_RAM_SECTION)));
73 //Transmit DMA descriptors
75  __attribute__((aligned(8), __section__(SC598_ETH1_RAM_SECTION)));
76 //Receive DMA descriptors
78  __attribute__((aligned(8), __section__(SC598_ETH1_RAM_SECTION)));
79 
80 #endif
81 
82 //Current transmit descriptor
83 static uint_t txIndex;
84 //Current receive descriptor
85 static uint_t rxIndex;
86 
87 
88 /**
89  * @brief ADSP-SC598 Ethernet MAC driver (EMAC0 instance)
90  **/
91 
93 {
95  ETH_MTU,
106  TRUE,
107  TRUE,
108  TRUE,
109  FALSE
110 };
111 
112 
113 /**
114  * @brief ADSP-SC598 Ethernet MAC initialization
115  * @param[in] interface Underlying network interface
116  * @return Error code
117  **/
118 
120 {
121  error_t error;
122  uint32_t temp;
123 
124  //Debug message
125  TRACE_INFO("Initializing ADSP-SC598 Ethernet MAC (EMAC0)...\r\n");
126 
127  //Save underlying network interface
128  nicDriverInterface = interface;
129 
130  //GPIO configuration
131  sc598Eth1InitGpio(interface);
132 
133  //Set DMA transfer format (little-endian)
134  *pREG_PADS0_PCFG0 &= ~BITM_PADS_PCFG0_EMAC0_ENDIANNESS;
135 
136  //Perform a software reset
137  *pREG_EMAC0_DMA_MODE |= BITM_EMAC_DMA_MODE_SWR;
138  //Wait for the reset to complete
139  while((*pREG_EMAC0_DMA_MODE & BITM_EMAC_DMA_MODE_SWR) != 0)
140  {
141  }
142 
143  //Adjust MDC clock range depending on SCLK0 frequency
144  *pREG_EMAC0_MDIO_ADDR = (4 << BITP_EMAC_MDIO_ADDR_CR);
145 
146  //Valid Ethernet PHY or switch driver?
147  if(interface->phyDriver != NULL)
148  {
149  //Ethernet PHY initialization
150  error = interface->phyDriver->init(interface);
151  }
152  else if(interface->switchDriver != NULL)
153  {
154  //Ethernet switch initialization
155  error = interface->switchDriver->init(interface);
156  }
157  else
158  {
159  //The interface is not properly configured
160  error = ERROR_FAILURE;
161  }
162 
163  //Any error to report?
164  if(error)
165  {
166  return error;
167  }
168 
169  //Use default MAC configuration
170  *pREG_EMAC0_MAC_CFG = BITM_EMAC_MAC_CFG_GPSLCE | BITM_EMAC_MAC_CFG_PS |
171  BITM_EMAC_MAC_CFG_DO;
172 
173  //Set the maximum packet size that can be accepted
174  temp = *pREG_EMAC0_MAC_EXT_CFG & ~BITM_EMAC_MAC_EXT_CFG_GPSL;
175  *pREG_EMAC0_MAC_EXT_CFG = temp | SC598_ETH1_RX_BUFFER_SIZE;
176 
177  //Configure MAC address filtering
178  sc598Eth1UpdateMacAddrFilter(interface);
179 
180  //Disable flow control
181  *pREG_EMAC0_Q0_TXFLOW_CTL = 0;
182  *pREG_EMAC0_RXFLOW_CTL = 0;
183 
184  //Enable the first RX queue
185  *pREG_EMAC0_RXQ_CTL0 = ENUM_EMAC_RXQ_CTL0_RXQ0EN_EN_DCB_GEN;
186 
187  //Configure DMA operating mode
188  *pREG_EMAC0_DMA_MODE = ENUM_EMAC_DMA_MODE_MODE0 |
189  ENUM_EMAC_DMA_MODE_DSPW_DISABLE;
190 
191  //Configure system bus mode
192  *pREG_EMAC0_DMA_SYSBMODE |= BITM_EMAC_DMA_SYSBMODE_AAL;
193 
194  //The DMA takes the descriptor table as contiguous
195  *pREG_EMAC0_DMA0_CTL = (0 << BITP_EMAC_DMA_CTL_DSL);
196  //Configure TX features
197  *pREG_EMAC0_DMA0_TXCTL = (32 << BITP_EMAC_DMA_TXCTL_TXPBL);
198 
199  //Configure RX features
200  *pREG_EMAC0_DMA0_RXCTL = (32 << BITP_EMAC_DMA_RXCTL_RXPBL) |
201  ((SC598_ETH1_RX_BUFFER_SIZE / 4) << BITP_EMAC_DMA_RXCTL_RBSZ_13_Y);
202 
203  //Enable store and forward mode for transmission
204  *pREG_EMAC0_TQ0_OPMODE |= (7 << BITP_EMAC_TQ_OPMODE_TQS) |
205  ENUM_EMAC_TQ_OPMODE_TXQEN_ENABLE | BITM_EMAC_TQ_OPMODE_TSF;
206 
207  //Enable store and forward mode for reception
208  *pREG_EMAC0_RQ0_OPMODE |= (7 << BITP_EMAC_RQ_OPMODE_RQS) |
209  BITM_EMAC_RQ_OPMODE_RSF;
210 
211  //Initialize DMA descriptor lists
212  sc598Eth1InitDmaDesc(interface);
213 
214  //Prevent interrupts from being generated when statistic counters reach
215  //half their maximum value
216  *pREG_EMAC0_MMC_TXIMSK = 0x0FFFFFFF;
217  *pREG_EMAC0_MMC_RXIMSK = 0x0FFFFFFF;
218  *pREG_EMAC0_MMC_IPC_RXIMSK = 0x3FFFFFFF;
219  *pREG_EMAC0_MMC_FPE_TXIMSK = 0x00000003;
220  *pREG_EMAC0_MMC_FPE_RXIMSK = 0x0000000F;
221 
222  //Disable MAC interrupts
223  *pREG_EMAC0_MAC_IEN = 0;
224 
225  //Enable the desired DMA interrupts
226  *pREG_EMAC0_DMA0_IEN = BITM_EMAC_DMA_IEN_NIE | BITM_EMAC_DMA_IEN_RIE |
227  BITM_EMAC_DMA_IEN_TIE;
228 
229  //Register interrupt handler
230  adi_int_InstallHandler(INTR_EMAC0_STAT, sc598Eth1IrqHandler, interface,
231  false);
232 
233  //Enable MAC transmission and reception
234  *pREG_EMAC0_MAC_CFG |= BITM_EMAC_MAC_CFG_TE | BITM_EMAC_MAC_CFG_RE;
235 
236  //Enable DMA transmission and reception
237  *pREG_EMAC0_DMA0_TXCTL |= BITM_EMAC_DMA_TXCTL_ST;
238  *pREG_EMAC0_DMA0_RXCTL |= BITM_EMAC_DMA_RXCTL_SR;
239 
240  //Accept any packets from the upper layer
241  osSetEvent(&interface->nicTxEvent);
242 
243  //Successful initialization
244  return NO_ERROR;
245 }
246 
247 
248 /**
249  * @brief GPIO configuration
250  * @param[in] interface Underlying network interface
251  **/
252 
253 __weak_func void sc598Eth1InitGpio(NetInterface *interface)
254 {
255 //EV-SC598-SOM evaluation board?
256 #if defined(USE_EV_SC598_SOM)
257  uint32_t temp;
258 
259  //Configure PH_03 (ETH0_MDC), PH_04 (ETH0_MDIO), PH_05 (ETH0_RXD0),
260  //PH_06 (ETH0_RXD1), PH_07 (ETH0_RXCLK_REFCLK), PH_08 (ETH0_RXCTL_RXDV),
261  //PH_09 (ETH0_TXD0), PH_10 (ETH0_TXD1), PH_11 (ETH0_RXD2), PH_12 (ETH0_RXD3),
262  //PH_13 (ETH0_TXCTL_TXEN), PH_14 (ETH0_TXCLK) and PH_15 (ETH0_TXD2)
263  temp = *pREG_PORTH_MUX;
264  temp = (temp & ~BITM_PORT_MUX_MUX3) | (0 << BITP_PORT_MUX_MUX3);
265  temp = (temp & ~BITM_PORT_MUX_MUX4) | (0 << BITP_PORT_MUX_MUX4);
266  temp = (temp & ~BITM_PORT_MUX_MUX5) | (0 << BITP_PORT_MUX_MUX5);
267  temp = (temp & ~BITM_PORT_MUX_MUX6) | (0 << BITP_PORT_MUX_MUX6);
268  temp = (temp & ~BITM_PORT_MUX_MUX7) | (0 << BITP_PORT_MUX_MUX7);
269  temp = (temp & ~BITM_PORT_MUX_MUX8) | (0 << BITP_PORT_MUX_MUX8);
270  temp = (temp & ~BITM_PORT_MUX_MUX9) | (0 << BITP_PORT_MUX_MUX9);
271  temp = (temp & ~BITM_PORT_MUX_MUX10) | (0 << BITP_PORT_MUX_MUX10);
272  temp = (temp & ~BITM_PORT_MUX_MUX11) | (0 << BITP_PORT_MUX_MUX11);
273  temp = (temp & ~BITM_PORT_MUX_MUX12) | (0 << BITP_PORT_MUX_MUX12);
274  temp = (temp & ~BITM_PORT_MUX_MUX13) | (0 << BITP_PORT_MUX_MUX13);
275  temp = (temp & ~BITM_PORT_MUX_MUX14) | (0 << BITP_PORT_MUX_MUX14);
276  temp = (temp & ~BITM_PORT_MUX_MUX15) | (0 << BITP_PORT_MUX_MUX15);
277  *pREG_PORTH_MUX = temp;
278 
279  //Select peripheral mode
280  *pREG_PORTH_FER_SET = BITM_PORT_FER_PX3 | BITM_PORT_FER_PX4 |
281  BITM_PORT_FER_PX5 | BITM_PORT_FER_PX6 | BITM_PORT_FER_PX7 |
282  BITM_PORT_FER_PX8 | BITM_PORT_FER_PX9 | BITM_PORT_FER_PX10 |
283  BITM_PORT_FER_PX11 | BITM_PORT_FER_PX12 | BITM_PORT_FER_PX13 |
284  BITM_PORT_FER_PX14 | BITM_PORT_FER_PX15;
285 
286  //Configure PI_00 (ETH0_TXD3)
287  temp = *pREG_PORTI_MUX;
288  temp = (temp & ~BITM_PORT_MUX_MUX0) | (0 << BITP_PORT_MUX_MUX0);
289  *pREG_PORTI_MUX = temp;
290 
291  //Select peripheral mode
292  *pREG_PORTI_FER_SET = BITM_PORT_FER_PX0;
293 
294  //Reset PHY transceiver (hard reset)
295  sc598Eth1ResetPhy(interface);
296 
297  //Select RGMII interface mode
298  temp = *pREG_PADS0_PCFG0 & ~BITM_PADS_PCFG0_EMACPHYISEL;
299  *pREG_PADS0_PCFG0 = temp | ENUM_PADS_PCFG0_EMACPHY_RGMII;
300 
301  //Reset PHY interface
302  *pREG_PADS0_PCFG0 |= BITM_PADS_PCFG0_EMACRESET;
303 #endif
304 }
305 
306 
307 /**
308  * @brief Reset PHY transceiver
309  * @param[in] interface Underlying network interface
310  **/
311 
312 __weak_func void sc598Eth1ResetPhy(NetInterface *interface)
313 {
314 }
315 
316 
317 /**
318  * @brief Initialize DMA descriptor lists
319  * @param[in] interface Underlying network interface
320  **/
321 
323 {
324  uint_t i;
325 
326  //Initialize TX DMA descriptor list
327  for(i = 0; i < SC598_ETH1_TX_BUFFER_COUNT; i++)
328  {
329  //The descriptor is initially owned by the application
330  txDmaDesc[i].tdes0 = 0;
331  txDmaDesc[i].tdes1 = 0;
332  txDmaDesc[i].tdes2 = 0;
333  txDmaDesc[i].tdes3 = 0;
334  }
335 
336  //Initialize TX descriptor index
337  txIndex = 0;
338 
339  //Initialize RX DMA descriptor list
340  for(i = 0; i < SC598_ETH1_RX_BUFFER_COUNT; i++)
341  {
342  //The descriptor is initially owned by the DMA
343  rxDmaDesc[i].rdes0 = adi_rtl_internal_to_system_addr(
344  (uint32_t)(uintptr_t) rxBuffer[i], 1);
345 
346  rxDmaDesc[i].rdes1 = 0;
347  rxDmaDesc[i].rdes2 = 0;
349  }
350 
351  //Initialize RX descriptor index
352  rxIndex = 0;
353 
354  //Start location of the TX descriptor list
355  *pREG_EMAC0_DMA0_TXDSC_ADDR = adi_rtl_internal_to_system_addr(
356  (uint32_t)(uintptr_t) &txDmaDesc[0], 1);
357 
358  //Length of the transmit descriptor ring
359  *pREG_EMAC0_DMA0_TXDSC_RLEN = SC598_ETH1_TX_BUFFER_COUNT - 1;
360 
361  //Start location of the RX descriptor list
362  *pREG_EMAC0_DMA0_RXDSC_ADDR = adi_rtl_internal_to_system_addr(
363  (uint32_t)(uintptr_t) &rxDmaDesc[0], 1);
364 
365  //Length of the receive descriptor ring
366  *pREG_EMAC0_DMA0_RXCTL2 = SC598_ETH1_RX_BUFFER_COUNT - 1;
367 }
368 
369 
370 /**
371  * @brief ADSP-SC598 Ethernet MAC timer handler
372  *
373  * This routine is periodically called by the TCP/IP stack to handle periodic
374  * operations such as polling the link state
375  *
376  * @param[in] interface Underlying network interface
377  **/
378 
379 void sc598Eth1Tick(NetInterface *interface)
380 {
381  //Valid Ethernet PHY or switch driver?
382  if(interface->phyDriver != NULL)
383  {
384  //Handle periodic operations
385  interface->phyDriver->tick(interface);
386  }
387  else if(interface->switchDriver != NULL)
388  {
389  //Handle periodic operations
390  interface->switchDriver->tick(interface);
391  }
392  else
393  {
394  //Just for sanity
395  }
396 }
397 
398 
399 /**
400  * @brief Enable interrupts
401  * @param[in] interface Underlying network interface
402  **/
403 
405 {
406  //Enable Ethernet MAC interrupts
407  adi_int_EnableInt(INTR_EMAC0_STAT, true);
408 
409  //Valid Ethernet PHY or switch driver?
410  if(interface->phyDriver != NULL)
411  {
412  //Enable Ethernet PHY interrupts
413  interface->phyDriver->enableIrq(interface);
414  }
415  else if(interface->switchDriver != NULL)
416  {
417  //Enable Ethernet switch interrupts
418  interface->switchDriver->enableIrq(interface);
419  }
420  else
421  {
422  //Just for sanity
423  }
424 }
425 
426 
427 /**
428  * @brief Disable interrupts
429  * @param[in] interface Underlying network interface
430  **/
431 
433 {
434  //Disable Ethernet MAC interrupts
435  adi_int_EnableInt(INTR_EMAC0_STAT, false);
436 
437  //Valid Ethernet PHY or switch driver?
438  if(interface->phyDriver != NULL)
439  {
440  //Disable Ethernet PHY interrupts
441  interface->phyDriver->disableIrq(interface);
442  }
443  else if(interface->switchDriver != NULL)
444  {
445  //Disable Ethernet switch interrupts
446  interface->switchDriver->disableIrq(interface);
447  }
448  else
449  {
450  //Just for sanity
451  }
452 }
453 
454 
455 /**
456  * @brief ADSP-SC598 Ethernet MAC interrupt service routine
457  * @param id Interrupt identifier
458  * @param param Unused parameter
459  **/
460 
461 void sc598Eth1IrqHandler(uint32_t id, void *param)
462 {
463  bool_t flag;
464  uint32_t status;
465 
466  //Interrupt service routine prologue
467  osEnterIsr();
468 
469  //This flag will be set if a higher priority task must be woken
470  flag = FALSE;
471 
472  //Read DMA status register
473  status = *pREG_EMAC0_DMA0_STAT;
474 
475  //Packet transmitted?
476  if((status & BITM_EMAC_DMA_STAT_TI) != 0)
477  {
478  //Clear TI interrupt flag
479  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA_STAT_TI;
480 
481  //Check whether the TX buffer is available for writing
482  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) == 0)
483  {
484  //Notify the TCP/IP stack that the transmitter is ready to send
485  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
486  }
487  }
488 
489  //Packet received?
490  if((status & BITM_EMAC_DMA_STAT_RI) != 0)
491  {
492  //Clear RI interrupt flag
493  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA_STAT_RI;
494 
495  //Set event flag
496  nicDriverInterface->nicEvent = TRUE;
497  //Notify the TCP/IP stack of the event
498  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
499  }
500 
501  //Clear NIS interrupt flag
502  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA_STAT_NIS;
503 
504  //Interrupt service routine epilogue
505  osExitIsr(flag);
506 }
507 
508 
509 /**
510  * @brief ADSP-SC598 Ethernet MAC event handler
511  * @param[in] interface Underlying network interface
512  **/
513 
515 {
516  error_t error;
517 
518  //Process all pending packets
519  do
520  {
521  //Read incoming packet
522  error = sc598Eth1ReceivePacket(interface);
523 
524  //No more data in the receive buffer?
525  } while(error != ERROR_BUFFER_EMPTY);
526 }
527 
528 
529 /**
530  * @brief Send a packet
531  * @param[in] interface Underlying network interface
532  * @param[in] buffer Multi-part buffer containing the data to send
533  * @param[in] offset Offset to the first data byte
534  * @param[in] ancillary Additional options passed to the stack along with
535  * the packet
536  * @return Error code
537  **/
538 
540  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
541 {
542  size_t length;
543 
544  //Retrieve the length of the packet
545  length = netBufferGetLength(buffer) - offset;
546 
547  //Check the frame length
549  {
550  //The transmitter can accept another packet
551  osSetEvent(&interface->nicTxEvent);
552  //Report an error
553  return ERROR_INVALID_LENGTH;
554  }
555 
556  //Make sure the current buffer is available for writing
557  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) != 0)
558  {
559  return ERROR_FAILURE;
560  }
561 
562  //Copy user data to the transmit buffer
563  netBufferRead(txBuffer[txIndex], buffer, offset, length);
564 
565  //Set the start address of the buffer
566  txDmaDesc[txIndex].tdes0 = adi_rtl_internal_to_system_addr(
567  (uint32_t)(uintptr_t) txBuffer[txIndex], 1);
568 
569  //Write the number of bytes to send
570  txDmaDesc[txIndex].tdes2 = EMAC_TDES2_IOC | (length & EMAC_TDES2_HL_B1L);
571  //Give the ownership of the descriptor to the DMA
573 
574  //Data synchronization barrier
575  __asm("dsb sy");
576 
577  //Clear TBU flag to resume processing
578  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA_STAT_TBU;
579  //Instruct the DMA to poll the transmit descriptor list
580  *pREG_EMAC0_DMA0_TXDSC_TLPTR = 0;
581 
582  //Increment index and wrap around if necessary
583  if(++txIndex >= SC598_ETH1_TX_BUFFER_COUNT)
584  {
585  txIndex = 0;
586  }
587 
588  //Check whether the next buffer is available for writing
589  if((txDmaDesc[txIndex].tdes3 & EMAC_TDES3_OWN) == 0)
590  {
591  //The transmitter can accept another packet
592  osSetEvent(&interface->nicTxEvent);
593  }
594 
595  //Data successfully written
596  return NO_ERROR;
597 }
598 
599 
600 /**
601  * @brief Receive a packet
602  * @param[in] interface Underlying network interface
603  * @return Error code
604  **/
605 
607 {
608  error_t error;
609  size_t n;
610  NetRxAncillary ancillary;
611 
612  //Current buffer available for reading?
613  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_OWN) == 0)
614  {
615  //FD and LD flags should be set
616  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_FD) != 0 &&
617  (rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_LD) != 0)
618  {
619  //Make sure no error occurred
620  if((rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_ES) == 0)
621  {
622  //Retrieve the length of the frame
623  n = rxDmaDesc[rxIndex].rdes3 & EMAC_RDES3_PL;
624  //Limit the number of data to read
626 
627  //Additional options can be passed to the stack along with the packet
628  ancillary = NET_DEFAULT_RX_ANCILLARY;
629 
630  //Pass the packet to the upper layer
631  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
632 
633  //Valid packet received
634  error = NO_ERROR;
635  }
636  else
637  {
638  //The received packet contains an error
639  error = ERROR_INVALID_PACKET;
640  }
641  }
642  else
643  {
644  //The packet is not valid
645  error = ERROR_INVALID_PACKET;
646  }
647 
648  //Set the start address of the buffer
649  rxDmaDesc[rxIndex].rdes0 = adi_rtl_internal_to_system_addr(
650  (uint32_t)(uintptr_t) rxBuffer[rxIndex], 1);
651 
652  //Give the ownership of the descriptor back to the DMA
654 
655  //Increment index and wrap around if necessary
656  if(++rxIndex >= SC598_ETH1_RX_BUFFER_COUNT)
657  {
658  rxIndex = 0;
659  }
660  }
661  else
662  {
663  //No more data in the receive buffer
664  error = ERROR_BUFFER_EMPTY;
665  }
666 
667  //Clear RBU flag to resume processing
668  *pREG_EMAC0_DMA0_STAT = BITM_EMAC_DMA_STAT_RBU;
669  //Instruct the DMA to poll the receive descriptor list
670  *pREG_EMAC0_DMA0_RXDSC_TLPTR = 0;
671 
672  //Return status code
673  return error;
674 }
675 
676 
677 /**
678  * @brief Configure MAC address filtering
679  * @param[in] interface Underlying network interface
680  * @return Error code
681  **/
682 
684 {
685  uint_t i;
686  uint_t j;
687  uint_t k;
688  uint32_t crc;
689  uint32_t hashTable[8];
690  MacAddr unicastMacAddr[3];
691  MacFilterEntry *entry;
692 
693  //Debug message
694  TRACE_DEBUG("Updating MAC filter...\r\n");
695 
696  //Promiscuous mode?
697  if(interface->promiscuous)
698  {
699  //Pass all incoming frames regardless of their destination address
700  *pREG_EMAC0_MACPKT_FILT = BITM_EMAC_MACPKT_FILT_PR;
701  }
702  else
703  {
704  //Set the MAC address of the station
705  *pREG_EMAC0_ADDR0_LO = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
706  *pREG_EMAC0_ADDR0_HI = interface->macAddr.w[2];
707 
708  //The MAC supports 3 additional addresses for unicast perfect filtering
709  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
710  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
711  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
712 
713  //The hash table is used for multicast address filtering
714  hashTable[0] = 0;
715  hashTable[1] = 0;
716  hashTable[2] = 0;
717  hashTable[3] = 0;
718  hashTable[4] = 0;
719  hashTable[5] = 0;
720  hashTable[6] = 0;
721  hashTable[7] = 0;
722 
723  //The MAC address filter contains the list of MAC addresses to accept
724  //when receiving an Ethernet frame
725  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
726  {
727  //Point to the current entry
728  entry = &interface->macAddrFilter[i];
729 
730  //Valid entry?
731  if(entry->refCount > 0)
732  {
733  //Multicast address?
734  if(macIsMulticastAddr(&entry->addr))
735  {
736  //Compute CRC over the current MAC address
737  crc = sc598Eth1CalcCrc(&entry->addr, sizeof(MacAddr));
738 
739  //The upper 8 bits in the CRC register are used to index the
740  //contents of the hash table
741  k = (crc >> 24) & 0xFF;
742 
743  //Update hash table contents
744  hashTable[k / 32] |= (1 << (k % 32));
745  }
746  else
747  {
748  //Up to 3 additional MAC addresses can be specified
749  if(j < 3)
750  {
751  //Save the unicast address
752  unicastMacAddr[j++] = entry->addr;
753  }
754  }
755  }
756  }
757 
758  //Configure the first unicast address filter
759  if(j >= 1)
760  {
761  //When the AE bit is set, the entry is used for perfect filtering
762  *pREG_EMAC0_ADDR1_LO = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
763  *pREG_EMAC0_ADDR1_HI = unicastMacAddr[0].w[2] | BITM_EMAC_ADDR_HI_AE;
764  }
765  else
766  {
767  //When the AE bit is cleared, the entry is ignored
768  *pREG_EMAC0_ADDR1_LO = 0;
769  *pREG_EMAC0_ADDR1_HI = 0;
770  }
771 
772  //Configure the second unicast address filter
773  if(j >= 2)
774  {
775  //When the AE bit is set, the entry is used for perfect filtering
776  *pREG_EMAC0_ADDR2_LO = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
777  *pREG_EMAC0_ADDR2_HI = unicastMacAddr[1].w[2] | BITM_EMAC_ADDR_HI_AE;
778  }
779  else
780  {
781  //When the AE bit is cleared, the entry is ignored
782  *pREG_EMAC0_ADDR2_LO = 0;
783  *pREG_EMAC0_ADDR2_HI = 0;
784  }
785 
786  //Configure the third unicast address filter
787  if(j >= 3)
788  {
789  //When the AE bit is set, the entry is used for perfect filtering
790  *pREG_EMAC0_ADDR3_LO = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
791  *pREG_EMAC0_ADDR3_HI = unicastMacAddr[2].w[2] | BITM_EMAC_ADDR_HI_AE;
792  }
793  else
794  {
795  //When the AE bit is cleared, the entry is ignored
796  *pREG_EMAC0_ADDR3_LO = 0;
797  *pREG_EMAC0_ADDR3_HI = 0;
798  }
799 
800  //Check whether frames with a multicast destination address should be
801  //accepted
802  if(interface->acceptAllMulticast)
803  {
804  //Configure the receive filter
805  *pREG_EMAC0_MACPKT_FILT = BITM_EMAC_MACPKT_FILT_HPF | BITM_EMAC_MACPKT_FILT_PM;
806  }
807  else
808  {
809  //Configure the receive filter
810  *pREG_EMAC0_MACPKT_FILT = BITM_EMAC_MACPKT_FILT_HPF | BITM_EMAC_MACPKT_FILT_HMC;
811 
812  //Configure the multicast hash table
813  *pREG_EMAC0_HASHTBL_REG0 = hashTable[0];
814  *pREG_EMAC0_HASHTBL_REG1 = hashTable[1];
815  *pREG_EMAC0_HASHTBL_REG2 = hashTable[2];
816  *pREG_EMAC0_HASHTBL_REG3 = hashTable[3];
817  *pREG_EMAC0_HASHTBL_REG4 = hashTable[4];
818  *pREG_EMAC0_HASHTBL_REG5 = hashTable[5];
819  *pREG_EMAC0_HASHTBL_REG6 = hashTable[6];
820  *pREG_EMAC0_HASHTBL_REG7 = hashTable[7];
821 
822  //Debug message
823  TRACE_DEBUG(" EMAC_HASHTBL_REG0 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG0);
824  TRACE_DEBUG(" EMAC_HASHTBL_REG1 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG1);
825  TRACE_DEBUG(" EMAC_HASHTBL_REG2 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG2);
826  TRACE_DEBUG(" EMAC_HASHTBL_REG3 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG3);
827  TRACE_DEBUG(" EMAC_HASHTBL_REG4 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG4);
828  TRACE_DEBUG(" EMAC_HASHTBL_REG5 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG5);
829  TRACE_DEBUG(" EMAC_HASHTBL_REG6 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG6);
830  TRACE_DEBUG(" EMAC_HASHTBL_REG7 = 0x%08" PRIX32 "\r\n", *pREG_EMAC0_HASHTBL_REG7);
831  }
832  }
833 
834  //Successful processing
835  return NO_ERROR;
836 }
837 
838 
839 /**
840  * @brief Adjust MAC configuration parameters for proper operation
841  * @param[in] interface Underlying network interface
842  * @return Error code
843  **/
844 
846 {
847  uint32_t config;
848 
849  //Read current MAC configuration
850  config = *pREG_EMAC0_MAC_CFG;
851 
852  //1000BASE-T operation mode?
853  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
854  {
855  config &= ~BITM_EMAC_MAC_CFG_PS;
856  config &= ~BITM_EMAC_MAC_CFG_FES;
857  }
858  //100BASE-TX operation mode?
859  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
860  {
861  config |= BITM_EMAC_MAC_CFG_PS;
862  config |= BITM_EMAC_MAC_CFG_FES;
863  }
864  //10BASE-T operation mode?
865  else
866  {
867  config |= BITM_EMAC_MAC_CFG_PS;
868  config &= ~BITM_EMAC_MAC_CFG_FES;
869  }
870 
871  //Half-duplex or full-duplex mode?
872  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
873  {
874  config |= BITM_EMAC_MAC_CFG_DM;
875  }
876  else
877  {
878  config &= ~BITM_EMAC_MAC_CFG_DM;
879  }
880 
881  //Update MAC configuration register
882  *pREG_EMAC0_MAC_CFG = config;
883 
884  //Successful processing
885  return NO_ERROR;
886 }
887 
888 
889 /**
890  * @brief Write PHY register
891  * @param[in] opcode Access type (2 bits)
892  * @param[in] phyAddr PHY address (5 bits)
893  * @param[in] regAddr Register address (5 bits)
894  * @param[in] data Register value
895  **/
896 
897 void sc598Eth1WritePhyReg(uint8_t opcode, uint8_t phyAddr,
898  uint8_t regAddr, uint16_t data)
899 {
900  uint32_t temp;
901 
902  //Valid opcode?
903  if(opcode == SMI_OPCODE_WRITE)
904  {
905  //Take care not to alter MDC clock configuration
906  temp = *pREG_EMAC0_MDIO_ADDR & BITM_EMAC_MDIO_ADDR_CR;
907  //Set up a write operation
908  temp |= BITM_EMAC_MDIO_ADDR_GOC_0 | BITM_EMAC_MDIO_ADDR_GB;
909  //PHY address
910  temp |= (phyAddr << BITP_EMAC_MDIO_ADDR_PA) & BITM_EMAC_MDIO_ADDR_PA;
911  //Register address
912  temp |= (regAddr << BITP_EMAC_MDIO_ADDR_RDA) & BITM_EMAC_MDIO_ADDR_RDA;
913 
914  //Data to be written in the PHY register
915  *pREG_EMAC0_MDIO_DATA = data & BITM_EMAC_MDIO_DATA_GD;
916 
917  //Start a write operation
918  *pREG_EMAC0_MDIO_ADDR = temp;
919  //Wait for the write to complete
920  while((*pREG_EMAC0_MDIO_ADDR & BITM_EMAC_MDIO_ADDR_GB) != 0)
921  {
922  }
923  }
924  else
925  {
926  //The MAC peripheral only supports standard Clause 22 opcodes
927  }
928 }
929 
930 
931 /**
932  * @brief Read PHY register
933  * @param[in] opcode Access type (2 bits)
934  * @param[in] phyAddr PHY address (5 bits)
935  * @param[in] regAddr Register address (5 bits)
936  * @return Register value
937  **/
938 
939 uint16_t sc598Eth1ReadPhyReg(uint8_t opcode, uint8_t phyAddr,
940  uint8_t regAddr)
941 {
942  uint16_t data;
943  uint32_t temp;
944 
945  //Valid opcode?
946  if(opcode == SMI_OPCODE_READ)
947  {
948  //Take care not to alter MDC clock configuration
949  temp = *pREG_EMAC0_MDIO_ADDR & BITM_EMAC_MDIO_ADDR_CR;
950 
951  //Set up a read operation
952  temp |= BITM_EMAC_MDIO_ADDR_GOC_1 | BITM_EMAC_MDIO_ADDR_GOC_0 |
953  BITM_EMAC_MDIO_ADDR_GB;
954 
955  //PHY address
956  temp |= (phyAddr << BITP_EMAC_MDIO_ADDR_PA) & BITM_EMAC_MDIO_ADDR_PA;
957  //Register address
958  temp |= (regAddr << BITP_EMAC_MDIO_ADDR_RDA) & BITM_EMAC_MDIO_ADDR_RDA;
959 
960  //Start a read operation
961  *pREG_EMAC0_MDIO_ADDR = temp;
962  //Wait for the read to complete
963  while((*pREG_EMAC0_MDIO_ADDR & BITM_EMAC_MDIO_ADDR_GB) != 0)
964  {
965  }
966 
967  //Get register value
968  data = *pREG_EMAC0_MDIO_DATA & BITM_EMAC_MDIO_DATA_GD;
969  }
970  else
971  {
972  //The MAC peripheral only supports standard Clause 22 opcodes
973  data = 0;
974  }
975 
976  //Return the value of the PHY register
977  return data;
978 }
979 
980 
981 /**
982  * @brief CRC calculation
983  * @param[in] data Pointer to the data over which to calculate the CRC
984  * @param[in] length Number of bytes to process
985  * @return Resulting CRC value
986  **/
987 
988 uint32_t sc598Eth1CalcCrc(const void *data, size_t length)
989 {
990  uint_t i;
991  uint_t j;
992  uint32_t crc;
993  const uint8_t *p;
994 
995  //Point to the data over which to calculate the CRC
996  p = (uint8_t *) data;
997  //CRC preset value
998  crc = 0xFFFFFFFF;
999 
1000  //Loop through data
1001  for(i = 0; i < length; i++)
1002  {
1003  //The message is processed bit by bit
1004  for(j = 0; j < 8; j++)
1005  {
1006  //Update CRC value
1007  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
1008  {
1009  crc = (crc << 1) ^ 0x04C11DB7;
1010  }
1011  else
1012  {
1013  crc = crc << 1;
1014  }
1015  }
1016  }
1017 
1018  //Return CRC value
1019  return ~crc;
1020 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define EMAC_TDES3_OWN
uint8_t opcode
Definition: dns_common.h:191
int bool_t
Definition: compiler_port.h:63
#define EMAC_RDES3_PL
Receive descriptor.
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:690
void sc598Eth1DisableIrq(NetInterface *interface)
Disable interrupts.
error_t sc598Eth1UpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
uint8_t p
Definition: ndp.h:300
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define EMAC_RDES3_BUF1V
__weak_func void sc598Eth1InitGpio(NetInterface *interface)
GPIO configuration.
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
#define EMAC_RDES3_ES
uint8_t data[]
Definition: ethernet.h:224
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:266
Transmit descriptor.
void sc598Eth1IrqHandler(uint32_t id, void *param)
ADSP-SC598 Ethernet MAC interrupt service routine.
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:418
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define osExitIsr(flag)
#define EMAC_TDES3_FD
__weak_func void sc598Eth1ResetPhy(NetInterface *interface)
Reset PHY transceiver.
error_t sc598Eth1UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define SMI_OPCODE_WRITE
Definition: nic.h:66
ADSP-SC598 Ethernet MAC driver (EMAC0 instance)
error_t sc598Eth1ReceivePacket(NetInterface *interface)
Receive a packet.
void sc598Eth1Tick(NetInterface *interface)
ADSP-SC598 Ethernet MAC timer handler.
#define SC598_ETH1_RAM_SECTION
#define FALSE
Definition: os_port.h:46
#define EMAC_TDES2_HL_B1L
error_t
Error codes.
Definition: error.h:43
#define EMAC_TDES3_LD
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:103
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:40
void sc598Eth1InitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
MacAddr addr
MAC address.
Definition: ethernet.h:265
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define NetTxAncillary
Definition: net_misc.h:36
#define SC598_ETH1_TX_BUFFER_COUNT
#define SMI_OPCODE_READ
Definition: nic.h:67
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
void sc598Eth1EventHandler(NetInterface *interface)
ADSP-SC598 Ethernet MAC event handler.
#define MIN(a, b)
Definition: os_port.h:63
uint16_t sc598Eth1ReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define rxBuffer
MacAddr
Definition: ethernet.h:197
#define EMAC_RDES3_FD
#define TRACE_DEBUG(...)
Definition: debug.h:119
#define EMAC_TDES2_IOC
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
error_t sc598Eth1SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
uint8_t n
void sc598Eth1WritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
MAC filter table entry.
Definition: ethernet.h:264
#define osEnterIsr()
const NicDriver sc598Eth1Driver
ADSP-SC598 Ethernet MAC driver (EMAC0 instance)
void sc598Eth1EnableIrq(NetInterface *interface)
Enable interrupts.
#define EMAC_RDES3_LD
#define EMAC_RDES3_IOC
#define EMAC_RDES3_OWN
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define SC598_ETH1_RX_BUFFER_SIZE
#define txDmaDesc
uint32_t sc598Eth1CalcCrc(const void *data, size_t length)
CRC calculation.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
#define SC598_ETH1_RX_BUFFER_COUNT
NIC driver.
Definition: nic.h:286
error_t sc598Eth1Init(NetInterface *interface)
ADSP-SC598 Ethernet MAC initialization.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:51
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define SC598_ETH1_TX_BUFFER_SIZE