am335x_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file am335x_eth_driver.c
3  * @brief Sitara AM335x Ethernet MAC controller
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL NIC_TRACE_LEVEL
31 
32 //Dependencies
33 #include "soc_am335x.h"
34 #include "hw_types.h"
35 #include "hw_cm_per.h"
36 #include "hw_control_am335x.h"
37 #include "hw_cpsw_ale.h"
38 #include "hw_cpsw_cpdma.h"
39 #include "hw_cpsw_port.h"
40 #include "hw_cpsw_sl.h"
41 #include "hw_cpsw_ss.h"
42 #include "hw_cpsw_wr.h"
43 #include "hw_mdio.h"
44 #include "interrupt.h"
45 #include "core/net.h"
47 #include "debug.h"
48 
49 //MDIO input clock frequency
50 #define MDIO_INPUT_CLK 125000000
51 //MDIO output clock frequency
52 #define MDIO_OUTPUT_CLK 1000000
53 
54 //Underlying network interface (port 1)
55 static NetInterface *nicDriverInterface1 = NULL;
56 //Underlying network interface (port 2)
57 static NetInterface *nicDriverInterface2 = NULL;
58 
59 //IAR EWARM compiler?
60 #if defined(__ICCARM__)
61 
62 //Transmit buffer (port 1)
63 #pragma data_alignment = 4
64 #pragma location = ".ram_no_cache"
65 static uint8_t txBuffer1[AM335X_ETH_TX_BUFFER_COUNT][AM335X_ETH_TX_BUFFER_SIZE];
66 //Transmit buffer (port 2)
67 #pragma data_alignment = 4
68 #pragma location = ".ram_no_cache"
69 static uint8_t txBuffer2[AM335X_ETH_TX_BUFFER_COUNT][AM335X_ETH_TX_BUFFER_SIZE];
70 //Receive buffer
71 #pragma data_alignment = 4
72 #pragma location = ".ram_no_cache"
74 //Transmit buffer descriptors (port 1)
75 #pragma data_alignment = 4
76 #pragma location = ".ram_cppi"
78 //Transmit buffer descriptors (port 2)
79 #pragma data_alignment = 4
80 #pragma location = ".ram_cppi"
82 //Receive buffer descriptors
83 #pragma data_alignment = 4
84 #pragma location = ".ram_cppi"
86 
87 //Keil MDK-ARM or GCC compiler?
88 #else
89 
90 //Transmit buffer (port 1)
92  __attribute__((aligned(4), __section__(".ram_no_cache")));
93 //Transmit buffer (port 2)
95  __attribute__((aligned(4), __section__(".ram_no_cache")));
96 //Receive buffer
98  __attribute__((aligned(4), __section__(".ram_no_cache")));
99 //Transmit buffer descriptors (port 1)
101  __attribute__((aligned(4), __section__(".ram_cppi")));
102 //Transmit buffer descriptors (port 2)
104  __attribute__((aligned(4), __section__(".ram_cppi")));
105 //Receive buffer descriptors
107  __attribute__((aligned(4), __section__(".ram_cppi")));
108 
109 #endif
110 
111 //Pointer to the current TX buffer descriptor (port1)
112 static Am335xTxBufferDesc *txCurBufferDesc1;
113 //Pointer to the current TX buffer descriptor (port 2)
114 static Am335xTxBufferDesc *txCurBufferDesc2;
115 //Pointer to the current RX buffer descriptor
116 static Am335xRxBufferDesc *rxCurBufferDesc;
117 
118 
119 /**
120  * @brief AM335x Ethernet MAC driver (port1)
121  **/
122 
124 {
126  ETH_MTU,
137  FALSE,
138  TRUE,
139  TRUE,
140  FALSE
141 };
142 
143 
144 /**
145  * @brief AM335x Ethernet MAC driver (port2)
146  **/
147 
149 {
151  ETH_MTU,
162  FALSE,
163  TRUE,
164  TRUE,
165  FALSE
166 };
167 
168 
169 /**
170  * @brief AM335x Ethernet MAC initialization (port 1)
171  * @param[in] interface Underlying network interface
172  * @return Error code
173  **/
174 
176 {
177  error_t error;
178  uint32_t temp;
179 
180  //Debug message
181  TRACE_INFO("Initializing AM335x Ethernet MAC (port 1)...\r\n");
182 
183  //Initialize CPSW instance
184  am335xEthInitInstance(interface);
185 
186  //Save underlying network interface
187  nicDriverInterface1 = interface;
188 
189  //PHY transceiver initialization
190  error = interface->phyDriver->init(interface);
191  //Failed to initialize PHY transceiver?
192  if(error)
193  return error;
194 
195  //Unspecifield MAC address?
196  if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
197  {
198  //Use the factory preprogrammed MAC address
199  interface->macAddr.b[0] = CONTROL_MAC_ID_HI_R(0) >> CONTROL_MAC_ID0_HI_MACADDR_47_40_SHIFT;
200  interface->macAddr.b[1] = CONTROL_MAC_ID_HI_R(0) >> CONTROL_MAC_ID0_HI_MACADDR_39_32_SHIFT;
201  interface->macAddr.b[2] = CONTROL_MAC_ID_HI_R(0) >> CONTROL_MAC_ID0_HI_MACADDR_31_24_SHIFT;
202  interface->macAddr.b[3] = CONTROL_MAC_ID_HI_R(0) >> CONTROL_MAC_ID0_HI_MACADDR_23_16_SHIFT;
203  interface->macAddr.b[4] = CONTROL_MAC_ID_LO_R(0) >> CONTROL_MAC_ID0_LO_MACADDR_15_8_SHIFT;
204  interface->macAddr.b[5] = CONTROL_MAC_ID_LO_R(0) >> CONTROL_MAC_ID0_LO_MACADDR_7_0_SHIFT;
205 
206  //Generate the 64-bit interface identifier
207  macAddrToEui64(&interface->macAddr, &interface->eui64);
208  }
209 
210  //Set port state to forward
211  temp = CPSW_ALE_PORTCTL_R(1) & ~CPSW_ALE_PORTCTL1_PORT_STATE;
213 
214  //Set the MAC address
215  CPSW_PORT1_SA_HI_R = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
216  CPSW_PORT1_SA_LO_R = interface->macAddr.w[2];
217 
218  //Configure VLAN identifier and VLAN priority
219  CPSW_PORT1_PORT_VLAN_R = (0 << CPSW_PORT_P1_PORT_VLAN_PORT_PRI_SHIFT) |
220  (CPSW_PORT1 << CPSW_PORT_P1_PORT_VLAN_PORT_VID_SHIFT);
221 
222  //Add a VLAN entry in the ALE table
224 
225  //Add a VLAN/unicast address entry in the ALE table
226  am335xEthAddVlanAddrEntry(CPSW_PORT1, CPSW_PORT1, &interface->macAddr);
227 
228  //Enable CPSW statistics
229  CPSW_SS_STAT_PORT_EN_R |= CPSW_SS_STAT_PORT_EN_P1_STAT_EN;
230 
231  //Enable TX and RX
232  CPSW_SL1_MACCONTROL_R = CPSW_SL_MACCONTROL_GMII_EN;
233 
234  //Accept any packets from the upper layer
235  osSetEvent(&interface->nicTxEvent);
236 
237  //Successful initialization
238  return NO_ERROR;
239 }
240 
241 
242 /**
243  * @brief AM335x Ethernet MAC initialization (port 2)
244  * @param[in] interface Underlying network interface
245  * @return Error code
246  **/
247 
249 {
250  error_t error;
251  uint32_t temp;
252 
253  //Debug message
254  TRACE_INFO("Initializing AM335x Ethernet MAC (port 2)...\r\n");
255 
256  //Initialize CPSW instance
257  am335xEthInitInstance(interface);
258 
259  //Save underlying network interface
260  nicDriverInterface2 = interface;
261 
262  //PHY transceiver initialization
263  error = interface->phyDriver->init(interface);
264  //Failed to initialize PHY transceiver?
265  if(error)
266  return error;
267 
268  //Unspecifield MAC address?
269  if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
270  {
271  //Use the factory preprogrammed MAC address
272  interface->macAddr.b[0] = CONTROL_MAC_ID_HI_R(1) >> CONTROL_MAC_ID1_HI_MACADDR_47_40_SHIFT;
273  interface->macAddr.b[1] = CONTROL_MAC_ID_HI_R(1) >> CONTROL_MAC_ID1_HI_MACADDR_39_32_SHIFT;
274  interface->macAddr.b[2] = CONTROL_MAC_ID_HI_R(1) >> CONTROL_MAC_ID1_HI_MACADDR_31_24_SHIFT;
275  interface->macAddr.b[3] = CONTROL_MAC_ID_HI_R(1) >> CONTROL_MAC_ID1_HI_MACADDR_23_16_SHIFT;
276  interface->macAddr.b[4] = CONTROL_MAC_ID_LO_R(1) >> CONTROL_MAC_ID1_LO_MACADDR_15_8_SHIFT;
277  interface->macAddr.b[5] = CONTROL_MAC_ID_LO_R(1) >> CONTROL_MAC_ID1_LO_MACADDR_7_0_SHIFT;
278 
279  //Generate the 64-bit interface identifier
280  macAddrToEui64(&interface->macAddr, &interface->eui64);
281  }
282 
283  //Set port state to forward
284  temp = CPSW_ALE_PORTCTL_R(2) & ~CPSW_ALE_PORTCTL2_PORT_STATE;
286 
287  //Set the MAC address
288  CPSW_PORT2_SA_HI_R = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
289  CPSW_PORT2_SA_LO_R = interface->macAddr.w[2];
290 
291  //Configure VLAN identifier and VLAN priority
292  CPSW_PORT2_PORT_VLAN_R = (0 << CPSW_PORT_P2_PORT_VLAN_PORT_PRI_SHIFT) |
293  (CPSW_PORT2 << CPSW_PORT_P2_PORT_VLAN_PORT_VID_SHIFT);
294 
295  //Add a VLAN entry in the ALE table
297 
298  //Add a VLAN/unicast address entry in the ALE table
299  am335xEthAddVlanAddrEntry(CPSW_PORT2, CPSW_PORT2, &interface->macAddr);
300 
301  //Enable CPSW statistics
302  CPSW_SS_STAT_PORT_EN_R |= CPSW_SS_STAT_PORT_EN_P2_STAT_EN;
303 
304  //Enable TX and RX
305  CPSW_SL2_MACCONTROL_R = CPSW_SL_MACCONTROL_GMII_EN;
306 
307  //Accept any packets from the upper layer
308  osSetEvent(&interface->nicTxEvent);
309 
310  //Successful initialization
311  return NO_ERROR;
312 }
313 
314 
315 /**
316  * @brief Initialize CPSW instance
317  * @param[in] interface Underlying network interface
318  **/
319 
321 {
322  uint_t i;
323  uint32_t temp;
324 #ifdef ti_sysbios_BIOS___VERS
325  Hwi_Params hwiParams;
326 #endif
327 
328  //Initialization sequence is performed once
329  if(nicDriverInterface1 == NULL && nicDriverInterface2 == NULL)
330  {
331  //Select the interface mode (MII/RMII/RGMII) and configure pin muxing
332  am335xEthInitGpio(interface);
333 
334  //Enable the CPSW subsystem clocks
335  CM_PER_CPGMAC0_CLKCTRL_R = CM_PER_CPGMAC0_CLKCTRL_MODULEMODE_ENABLE;
336 
337  //Wait for the CPSW module to be fully functional
338  do
339  {
340  //Get module idle status
341  temp = (CM_PER_CPGMAC0_CLKCTRL_R & CM_PER_CPGMAC0_CLKCTRL_IDLEST) >>
342  CM_PER_CPGMAC0_CLKCTRL_IDLEST_SHIFT;
343 
344  //Keep looping as long as the module is not fully functional
345  } while(temp != CM_PER_CPGMAC0_CLKCTRL_IDLEST_FUNC);
346 
347  //Start a software forced wake-up transition
348  CM_PER_CPSW_CLKSTCTRL_R = CM_PER_CPSW_CLKSTCTRL_CLKTRCTRL_SW_WKUP;
349 
350  //Wait for the CPSW 125 MHz OCP clock to be active
351  do
352  {
353  //Get the state of the CPSW 125 MHz OCP clock
354  temp = (CM_PER_CPSW_CLKSTCTRL_R & CM_PER_CPSW_CLKSTCTRL_CLKACTIVITY_CPSW_125MHZ_GCLK) >>
355  CM_PER_CPSW_CLKSTCTRL_CLKACTIVITY_CPSW_125MHZ_GCLK_SHIFT;
356 
357  //Keep looping as long as the clock is inactive
358  } while(temp != CM_PER_CPSW_CLKSTCTRL_CLKACTIVITY_CPSW_125MHZ_GCLK_ACT);
359 
360  //Reset CPSW subsystem
361  CPSW_SS_SOFT_RESET_R = CPSW_SS_SOFT_RESET_SOFT_RESET;
362  //Wait for the reset to complete
363  while(CPSW_SS_SOFT_RESET_R & CPSW_SS_SOFT_RESET_SOFT_RESET);
364 
365  //Reset CPSW wrapper module
366  CPSW_WR_SOFT_RESET_R = CPSW_WR_SOFT_RESET_SOFT_RESET;
367  //Wait for the reset to complete
368  while(CPSW_WR_SOFT_RESET_R & CPSW_WR_SOFT_RESET_SOFT_RESET);
369 
370  //Reset CPSW sliver 1 logic
371  CPSW_SL1_SOFT_RESET_R = CPSW_SL_SOFT_RESET_SOFT_RESET;
372  //Wait for the reset to complete
373  while(CPSW_SL1_SOFT_RESET_R & CPSW_SL_SOFT_RESET_SOFT_RESET);
374 
375  //Reset CPSW sliver 2 logic
376  CPSW_SL2_SOFT_RESET_R = CPSW_SL_SOFT_RESET_SOFT_RESET;
377  //Wait for the reset to complete
378  while(CPSW_SL2_SOFT_RESET_R & CPSW_SL_SOFT_RESET_SOFT_RESET);
379 
380  //Reset CPSW CPDMA module
381  CPSW_CPDMA_CPDMA_SOFT_RESET_R = CPSW_CPDMA_CPDMA_SOFT_RESET_SOFT_RESET;
382  //Wait for the reset to complete
383  while(CPSW_CPDMA_CPDMA_SOFT_RESET_R & CPSW_CPDMA_CPDMA_SOFT_RESET_SOFT_RESET);
384 
385  //Initialize the HDPs and the CPs to NULL
386  for(i = CPSW_CH0; i <= CPSW_CH7; i++)
387  {
388  //TX head descriptor pointer
389  CPSW_CPDMA_TX_HDP_R(i) = 0;
390  //TX completion pointer
391  CPSW_CPDMA_TX_CP_R(i) = 0;
392  //RX head descriptor pointer
393  CPSW_CPDMA_RX_HDP_R(i) = 0;
394  //RX completion pointer
395  CPSW_CPDMA_RX_CP_R(i) = 0;
396  }
397 
398  //Enable ALE and clear ALE address table
399  CPSW_ALE_CONTROL_R = CPSW_ALE_CONTROL_ENABLE_ALE |
400  CPSW_ALE_CONTROL_CLEAR_TABLE;
401 
402  //For dual MAC mode, configure VLAN aware mode
403  CPSW_ALE_CONTROL_R |= CPSW_ALE_CONTROL_ALE_VLAN_AWARE;
404 
405  //Set dual MAC mode for port 0
406  temp = CPSW_PORT0_TX_IN_CTL_R & ~CPSW_PORT_P0_TX_IN_CTL_TX_IN_SEL;
407  CPSW_PORT0_TX_IN_CTL_R = temp | CPSW_PORT_P0_TX_IN_CTL_TX_IN_DUAL_MAC;
408 
409  //Set port 0 state to forward
410  temp = CPSW_ALE_PORTCTL_R(0) & ~CPSW_ALE_PORTCTL0_PORT_STATE;
412 
413  //Enable CPSW statistics
414  CPSW_SS_STAT_PORT_EN_R = CPSW_SS_STAT_PORT_EN_P0_STAT_EN;
415 
416  //Configure TX and RX buffer descriptors
417  am335xEthInitBufferDesc(interface);
418 
419  //Acknowledge TX and interrupts for proper interrupt pulsing
422 
423  //Enable channel 1 and 2 interrupts of the DMA engine
425  //Enable TX completion interrupts
426  CPSW_WR_C_TX_EN_R(CPSW_CORE0) |= (1 << CPSW_CH1) | (1 << CPSW_CH2);
427 
428  //Enable channel 0 interrupts of the DMA engine
430  //Enable RX completion interrupts
432 
433 #ifdef ti_sysbios_BIOS___VERS
434  //Configure TX interrupt
435  Hwi_Params_init(&hwiParams);
436  hwiParams.enableInt = FALSE;
437  hwiParams.priority = AM335X_ETH_IRQ_PRIORITY;
438 
439  //Register TX interrupt handler
440  Hwi_create(SYS_INT_3PGSWTXINT0, (Hwi_FuncPtr) am335xEthTxIrqHandler,
441  &hwiParams, NULL);
442 
443  //Configure RX interrupt
444  Hwi_Params_init(&hwiParams);
445  hwiParams.enableInt = FALSE;
446  hwiParams.priority = AM335X_ETH_IRQ_PRIORITY;
447 
448  //Register RX interrupt handler
449  Hwi_create(SYS_INT_3PGSWRXINT0, (Hwi_FuncPtr) am335xEthRxIrqHandler,
450  &hwiParams, NULL);
451 #else
452  //Register interrupt handlers
453  IntRegister(SYS_INT_3PGSWTXINT0, am335xEthTxIrqHandler);
454  IntRegister(SYS_INT_3PGSWRXINT0, am335xEthRxIrqHandler);
455 
456  //Configure TX interrupt priority
457  IntPrioritySet(SYS_INT_3PGSWTXINT0, AM335X_ETH_IRQ_PRIORITY,
458  AINTC_HOSTINT_ROUTE_IRQ);
459 
460  //Configure RX interrupt priority
461  IntPrioritySet(SYS_INT_3PGSWRXINT0, AM335X_ETH_IRQ_PRIORITY,
462  AINTC_HOSTINT_ROUTE_IRQ);
463 #endif
464 
465  //Enable the transmission and reception
466  CPSW_CPDMA_TX_CONTROL_R = CPSW_CPDMA_TX_CONTROL_TX_EN;
467  CPSW_CPDMA_RX_CONTROL_R = CPSW_CPDMA_RX_CONTROL_RX_EN;
468 
469  //Calculate the MDC clock divider to be used
470  temp = (MDIO_INPUT_CLK / MDIO_OUTPUT_CLK) - 1;
471 
472  //Initialize MDIO interface
473  MDIO_CONTROL_R = MDIO_CONTROL_ENABLE |
474  MDIO_CONTROL_FAULTENB | (temp & MDIO_CONTROL_CLKDIV);
475  }
476 }
477 
478 
479 //BeagleBone Black, TMDSSK3358, OSD3358-SM-RED or SBC DIVA board?
480 #if defined(USE_BEAGLEBONE_BLACK) || defined(USE_TMDSSK3358) || \
481  defined(USE_OSD3358_SM_RED) || defined(USE_SBC_DIVA)
482 
483 /**
484  * @brief GPIO configuration
485  * @param[in] interface Underlying network interface
486  **/
487 
488 void am335xEthInitGpio(NetInterface *interface)
489 {
490 //BeagleBone Black board?
491 #if defined(USE_BEAGLEBONE_BLACK)
492  //Select MII interface mode for port 1
494 
495  //Configure MII1_TX_CLK (GPIO3_9)
496  CONTROL_CONF_MII1_TXCLK_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(0);
497  //Configure MII1_TX_EN (GPIO3_3)
498  CONTROL_CONF_MII1_TXEN_R = CONTROL_CONF_MUXMODE(0);
499  //Configure MII1_TXD0 (GPIO0_28)
500  CONTROL_CONF_MII1_TXD0_R = CONTROL_CONF_MUXMODE(0);
501  //Configure MII1_TXD1 (GPIO0_21)
502  CONTROL_CONF_MII1_TXD1_R = CONTROL_CONF_MUXMODE(0);
503  //Configure MII1_TXD2 (GPIO0_17)
504  CONTROL_CONF_MII1_TXD2_R = CONTROL_CONF_MUXMODE(0);
505  //Configure MII1_TXD3 (GPIO0_16)
506  CONTROL_CONF_MII1_TXD3_R = CONTROL_CONF_MUXMODE(0);
507 
508  //Configure MII1_RX_CLK (GPIO3_10)
509  CONTROL_CONF_MII1_RXCLK_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(0);
510  //Configure MII1_RXD0 (GPIO2_21)
511  CONTROL_CONF_MII1_RXD0_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(0);
512  //Configure MII1_RXD1 (GPIO2_20)
513  CONTROL_CONF_MII1_RXD1_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(0);
514  //Configure MII1_RXD2 (GPIO2_19)
515  CONTROL_CONF_MII1_RXD2_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(0);
516  //Configure MII1_RXD3 (GPIO2_18)
517  CONTROL_CONF_MII1_RXD3_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(0);
518  //Configure MII1_COL (GPIO3_0)
519  CONTROL_CONF_MII1_COL_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(0);
520  //Configure MII1_CRS (GPIO3_1)
521  CONTROL_CONF_MII1_CRS_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(0);
522  //Configure MII1_RX_ER (GPIO3_2)
523  CONTROL_CONF_MII1_RXERR_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(0);
524  //Configure MII1_RX_DV (GPIO3_4)
525  CONTROL_CONF_MII1_RXDV_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(0);
526 
527  //Configure MDIO (GPIO0_0)
528  CONTROL_CONF_MDIO_DATA_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_PULLUPSEL |
529  CONTROL_CONF_MUXMODE(0);
530 
531  //Configure MDC (GPIO0_1)
532  CONTROL_CONF_MDIO_CLK_R = CONTROL_CONF_PULLUPSEL | CONTROL_CONF_MUXMODE(0);
533 
534 //TMDSSK3358 board?
535 #elif defined(USE_TMDSSK3358)
536  //Select RGMII interface mode for both port 1 and port 2
539 
540  //Configure RGMII1_TCLK (GPIO3_9)
541  CONTROL_CONF_MII1_TXCLK_R = CONTROL_CONF_MUXMODE(2);
542  //Configure RGMII1_TCTL (GPIO3_3)
543  CONTROL_CONF_MII1_TXEN_R = CONTROL_CONF_MUXMODE(2);
544  //Configure RGMII1_TD0 (GPIO0_28)
545  CONTROL_CONF_MII1_TXD0_R = CONTROL_CONF_MUXMODE(2);
546  //Configure RGMII1_TD1 (GPIO0_21)
547  CONTROL_CONF_MII1_TXD1_R = CONTROL_CONF_MUXMODE(2);
548  //Configure RGMII1_TD2 (GPIO0_17)
549  CONTROL_CONF_MII1_TXD2_R = CONTROL_CONF_MUXMODE(2);
550  //Configure RGMII1_TD3 (GPIO0_16)
551  CONTROL_CONF_MII1_TXD3_R = CONTROL_CONF_MUXMODE(2);
552 
553  //Configure RGMII1_RCLK (GPIO3_10)
554  CONTROL_CONF_MII1_RXCLK_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
555  //Configure RGMII1_RCTL (GPIO3_4)
556  CONTROL_CONF_MII1_RXDV_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
557  //Configure RGMII1_RD0 (GPIO2_21)
558  CONTROL_CONF_MII1_RXD0_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
559  //Configure /RGMII1_RD1 (GPIO2_20)
560  CONTROL_CONF_MII1_RXD1_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
561  //Configure RGMII1_RD2 (GPIO2_19)
562  CONTROL_CONF_MII1_RXD2_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
563  //Configure RGMII1_RD3 (GPIO2_18)
564  CONTROL_CONF_MII1_RXD3_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
565 
566  //Configure RGMII2_TCLK (GPIO1_22/GPMC_A6)
567  CONTROL_CONF_GPMC_A_R(6) = CONTROL_CONF_MUXMODE(2);
568  //Configure RGMII2_TCTL (GPIO1_16/GPMC_A0)
569  CONTROL_CONF_GPMC_A_R(0) = CONTROL_CONF_MUXMODE(2);
570  //Configure RGMII2_TD0 (GPIO1_21/GPMC_A5)
571  CONTROL_CONF_GPMC_A_R(5) = CONTROL_CONF_MUXMODE(2);
572  //Configure RGMII2_TD1 (GPIO1_20/GPMC_A4)
573  CONTROL_CONF_GPMC_A_R(4) = CONTROL_CONF_MUXMODE(2);
574  //Configure RGMII2_TD2 (GPIO1_19/GPMC_A3)
575  CONTROL_CONF_GPMC_A_R(3) = CONTROL_CONF_MUXMODE(2);
576  //Configure RGMII2_TD3 (GPIO1_18/GPMC_A2)
577  CONTROL_CONF_GPMC_A_R(2) = CONTROL_CONF_MUXMODE(2);
578 
579  //Configure RGMII2_RCLK (GPIO1_23/GPMC_A7)
580  CONTROL_CONF_GPMC_A_R(7) = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
581  //Configure RGMII2_RCTL (GPIO1_17/GPMC_A1)
582  CONTROL_CONF_GPMC_A_R(1) = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
583  //Configure RGMII2_RD0 (GPIO1_27/GPMC_A11)
584  CONTROL_CONF_GPMC_A_R(11) = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
585  //Configure RGMII2_RD1 (GPIO1_26/GPMC_A10)
586  CONTROL_CONF_GPMC_A_R(10) = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
587  //Configure RGMII2_RD2 (GPIO1_25/GPMC_A9)
588  CONTROL_CONF_GPMC_A_R(9) = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
589  //Configure RGMII2_RD3 (GPIO1_24/GPMC_A8)
590  CONTROL_CONF_GPMC_A_R(8) = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
591 
592  //Configure MDIO (GPIO0_0)
593  CONTROL_CONF_MDIO_DATA_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_PULLUPSEL |
594  CONTROL_CONF_MUXMODE(0);
595 
596  //Configure MDC (GPIO0_1)
597  CONTROL_CONF_MDIO_CLK_R = CONTROL_CONF_PULLUPSEL | CONTROL_CONF_MUXMODE(0);
598 
599 //OSD3358-SM-RED board?
600 #elif defined(USE_OSD3358_SM_RED)
601  //Select RGMII interface mode for both port 1
603 
604  //Configure RGMII1_TCLK (GPIO3_9)
605  CONTROL_CONF_MII1_TXCLK_R = CONTROL_CONF_MUXMODE(2);
606  //Configure RGMII1_TCTL (GPIO3_3)
607  CONTROL_CONF_MII1_TXEN_R = CONTROL_CONF_MUXMODE(2);
608  //Configure RGMII1_TD0 (GPIO0_28)
609  CONTROL_CONF_MII1_TXD0_R = CONTROL_CONF_MUXMODE(2);
610  //Configure RGMII1_TD1 (GPIO0_21)
611  CONTROL_CONF_MII1_TXD1_R = CONTROL_CONF_MUXMODE(2);
612  //Configure RGMII1_TD2 (GPIO0_17)
613  CONTROL_CONF_MII1_TXD2_R = CONTROL_CONF_MUXMODE(2);
614  //Configure RGMII1_TD3 (GPIO0_16)
615  CONTROL_CONF_MII1_TXD3_R = CONTROL_CONF_MUXMODE(2);
616 
617  //Configure RGMII1_RCLK (GPIO3_10)
618  CONTROL_CONF_MII1_RXCLK_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
619  //Configure RGMII1_RCTL (GPIO3_4)
620  CONTROL_CONF_MII1_RXDV_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
621  //Configure RGMII1_RD0 (GPIO2_21)
622  CONTROL_CONF_MII1_RXD0_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
623  //Configure /RGMII1_RD1 (GPIO2_20)
624  CONTROL_CONF_MII1_RXD1_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
625  //Configure RGMII1_RD2 (GPIO2_19)
626  CONTROL_CONF_MII1_RXD2_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
627  //Configure RGMII1_RD3 (GPIO2_18)
628  CONTROL_CONF_MII1_RXD3_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
629 
630  //Configure MDIO (GPIO0_0)
631  CONTROL_CONF_MDIO_DATA_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_PULLUPSEL |
632  CONTROL_CONF_MUXMODE(0);
633 
634  //Configure MDC (GPIO0_1)
635  CONTROL_CONF_MDIO_CLK_R = CONTROL_CONF_PULLUPSEL | CONTROL_CONF_MUXMODE(0);
636 
637 //SBC DIVA board?
638 #elif defined(USE_SBC_DIVA)
639  //Select RMII interface mode for port 1 and RGMII interface mode for port 2
640  CONTROL_GMII_SEL_R = CONTROL_GMII_SEL_RMII1_IO_CLK_EN |
642 
643  //Configure RMII1_REF_CLK (GPIO0_29)
644  CONTROL_CONF_RMII1_REFCLK_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(0);
645 
646  //Configure RMII1_TX_EN (GPIO3_3)
647  CONTROL_CONF_MII1_TXEN_R = CONTROL_CONF_MUXMODE(1);
648  //Configure RMII1_TXD0 (GPIO0_28)
649  CONTROL_CONF_MII1_TXD0_R = CONTROL_CONF_MUXMODE(1);
650  //Configure RMII1_TXD1 (GPIO0_21)
651  CONTROL_CONF_MII1_TXD1_R = CONTROL_CONF_MUXMODE(1);
652 
653  //Configure RMII1_RXD0 (GPIO2.21)
654  CONTROL_CONF_MII1_RXD0_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(1);
655  //Configure RMII1_RXD1 (GPIO2.20)
656  CONTROL_CONF_MII1_RXD1_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(1);
657  //Configure RMII1_CRS_DV (GPIO3_1)
658  CONTROL_CONF_MII1_CRS_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(1);
659  //Configure RMII1_RX_ER (GPIO3_2)
660  CONTROL_CONF_MII1_RXERR_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(1);
661 
662  //Configure RGMII2_TCLK (GPIO1_22/GPMC_A6)
663  CONTROL_CONF_GPMC_A_R(6) = CONTROL_CONF_MUXMODE(2);
664  //Configure RGMII2_TCTL (GPIO1_16/GPMC_A0)
665  CONTROL_CONF_GPMC_A_R(0) = CONTROL_CONF_MUXMODE(2);
666  //Configure RGMII2_TD0 (GPIO1_21/GPMC_A5)
667  CONTROL_CONF_GPMC_A_R(5) = CONTROL_CONF_MUXMODE(2);
668  //Configure RGMII2_TD1 (GPIO1_20/GPMC_A4)
669  CONTROL_CONF_GPMC_A_R(4) = CONTROL_CONF_MUXMODE(2);
670  //Configure RGMII2_TD2 (GPIO1_19/GPMC_A3)
671  CONTROL_CONF_GPMC_A_R(3) = CONTROL_CONF_MUXMODE(2);
672  //Configure RGMII2_TD3 (GPIO1_18/GPMC_A2)
673  CONTROL_CONF_GPMC_A_R(2) = CONTROL_CONF_MUXMODE(2);
674 
675  //Configure RGMII2_RCLK (GPIO1_23/GPMC_A7)
676  CONTROL_CONF_GPMC_A_R(7) = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
677  //Configure RGMII2_RCTL (GPIO1_17/GPMC_A1)
678  CONTROL_CONF_GPMC_A_R(1) = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
679  //Configure RGMII2_RD0 (GPIO1_27/GPMC_A11)
680  CONTROL_CONF_GPMC_A_R(11) = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
681  //Configure RGMII2_RD1 (GPIO1_26/GPMC_A10)
682  CONTROL_CONF_GPMC_A_R(10) = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
683  //Configure RGMII2_RD2 (GPIO1_25/GPMC_A9)
684  CONTROL_CONF_GPMC_A_R(9) = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
685  //Configure RGMII2_RD3 (GPIO1_24/GPMC_A8)
686  CONTROL_CONF_GPMC_A_R(8) = CONTROL_CONF_RXACTIVE | CONTROL_CONF_MUXMODE(2);
687 
688  //Configure MDIO (GPIO0_0)
689  CONTROL_CONF_MDIO_DATA_R = CONTROL_CONF_RXACTIVE | CONTROL_CONF_PULLUPSEL |
690  CONTROL_CONF_MUXMODE(0);
691 
692  //Configure MDC (GPIO0_1)
693  CONTROL_CONF_MDIO_CLK_R = CONTROL_CONF_PULLUPSEL | CONTROL_CONF_MUXMODE(0);
694 #endif
695 }
696 
697 #endif
698 
699 
700 /**
701  * @brief Initialize buffer descriptor lists
702  * @param[in] interface Underlying network interface
703  **/
704 
706 {
707  uint_t i;
708  uint_t nextIndex;
709  uint_t prevIndex;
710 
711  //Initialize TX buffer descriptor list (port 1)
712  for(i = 0; i < AM335X_ETH_TX_BUFFER_COUNT; i++)
713  {
714  //Index of the next buffer
715  nextIndex = (i + 1) % AM335X_ETH_TX_BUFFER_COUNT;
716  //Index of the previous buffer
718 
719  //Next descriptor pointer
720  txBufferDesc1[i].word0 = (uint32_t) NULL;
721  //Buffer pointer
722  txBufferDesc1[i].word1 = (uint32_t) txBuffer1[i];
723  //Buffer offset and buffer length
724  txBufferDesc1[i].word2 = 0;
725  //Status flags and packet length
726  txBufferDesc1[i].word3 = 0;
727 
728  //Form a doubly linked list
729  txBufferDesc1[i].next = &txBufferDesc1[nextIndex];
730  txBufferDesc1[i].prev = &txBufferDesc1[prevIndex];
731  }
732 
733  //Point to the very first descriptor
734  txCurBufferDesc1 = &txBufferDesc1[0];
735 
736  //Mark the end of the queue
737  txCurBufferDesc1->prev->word3 = CPSW_TX_WORD3_SOP |
739 
740  //Initialize TX buffer descriptor list (port 2)
741  for(i = 0; i < AM335X_ETH_TX_BUFFER_COUNT; i++)
742  {
743  //Index of the next buffer
744  nextIndex = (i + 1) % AM335X_ETH_TX_BUFFER_COUNT;
745  //Index of the previous buffer
747 
748  //Next descriptor pointer
749  txBufferDesc2[i].word0 = (uint32_t) NULL;
750  //Buffer pointer
751  txBufferDesc2[i].word1 = (uint32_t) txBuffer2[i];
752  //Buffer offset and buffer length
753  txBufferDesc2[i].word2 = 0;
754  //Status flags and packet length
755  txBufferDesc2[i].word3 = 0;
756 
757  //Form a doubly linked list
758  txBufferDesc2[i].next = &txBufferDesc2[nextIndex];
759  txBufferDesc2[i].prev = &txBufferDesc2[prevIndex];
760  }
761 
762  //Point to the very first descriptor
763  txCurBufferDesc2 = &txBufferDesc2[0];
764 
765  //Mark the end of the queue
766  txCurBufferDesc2->prev->word3 = CPSW_TX_WORD3_SOP |
768 
769  //Initialize RX buffer descriptor list
770  for(i = 0; i < AM335X_ETH_RX_BUFFER_COUNT; i++)
771  {
772  //Index of the next buffer
773  nextIndex = (i + 1) % AM335X_ETH_RX_BUFFER_COUNT;
774  //Index of the previous buffer
776 
777  //Next descriptor pointer
778  rxBufferDesc[i].word0 = (uint32_t) &rxBufferDesc[nextIndex];
779  //Buffer pointer
780  rxBufferDesc[i].word1 = (uint32_t) rxBuffer[i];
781  //Buffer offset and buffer length
782  rxBufferDesc[i].word2 = AM335X_ETH_RX_BUFFER_SIZE;
783  //Status flags and packet length
784  rxBufferDesc[i].word3 = CPSW_RX_WORD3_OWNER;
785 
786  //Form a doubly linked list
787  rxBufferDesc[i].next = &rxBufferDesc[nextIndex];
788  rxBufferDesc[i].prev = &rxBufferDesc[prevIndex];
789  }
790 
791  //Point to the very first descriptor
792  rxCurBufferDesc = &rxBufferDesc[0];
793 
794  //Mark the end of the queue
795  rxCurBufferDesc->prev->word0 = (uint32_t) NULL;
796 
797  //Write the RX DMA head descriptor pointer
798  CPSW_CPDMA_RX_HDP_R(CPSW_CH0) = (uint32_t) rxCurBufferDesc;
799 }
800 
801 
802 /**
803  * @brief AM335x Ethernet MAC timer handler
804  *
805  * This routine is periodically called by the TCP/IP stack to
806  * handle periodic operations such as polling the link state
807  *
808  * @param[in] interface Underlying network interface
809  **/
810 
811 void am335xEthTick(NetInterface *interface)
812 {
813  //Handle periodic operations
814  interface->phyDriver->tick(interface);
815 
816  //Misqueued buffer condition?
817  if(rxCurBufferDesc->word3 & CPSW_RX_WORD3_OWNER)
818  {
819  if(CPSW_CPDMA_RX_HDP_R(CPSW_CH0) == 0)
820  {
821  //The host acts on the misqueued buffer condition by writing the added
822  //buffer descriptor address to the appropriate RX DMA head descriptor
823  //pointer
824  CPSW_CPDMA_RX_HDP_R(CPSW_CH0) = (uint32_t) rxCurBufferDesc;
825  }
826  }
827 }
828 
829 
830 /**
831  * @brief Enable interrupts
832  * @param[in] interface Underlying network interface
833  **/
834 
836 {
837 #ifdef ti_sysbios_BIOS___VERS
838  //Enable Ethernet MAC interrupts
839  Hwi_enableInterrupt(SYS_INT_3PGSWTXINT0);
840  Hwi_enableInterrupt(SYS_INT_3PGSWRXINT0);
841 #else
842  //Enable Ethernet MAC interrupts
843  IntSystemEnable(SYS_INT_3PGSWTXINT0);
844  IntSystemEnable(SYS_INT_3PGSWRXINT0);
845 #endif
846 
847  //Enable Ethernet PHY interrupts
848  interface->phyDriver->enableIrq(interface);
849 }
850 
851 
852 /**
853  * @brief Disable interrupts
854  * @param[in] interface Underlying network interface
855  **/
856 
858 {
859 #ifdef ti_sysbios_BIOS___VERS
860  //Disable Ethernet MAC interrupts
861  Hwi_disableInterrupt(SYS_INT_3PGSWTXINT0);
862  Hwi_disableInterrupt(SYS_INT_3PGSWRXINT0);
863 #else
864  //Disable Ethernet MAC interrupts
865  IntSystemDisable(SYS_INT_3PGSWTXINT0);
866  IntSystemDisable(SYS_INT_3PGSWRXINT0);
867 #endif
868 
869  //Disable Ethernet PHY interrupts
870  interface->phyDriver->disableIrq(interface);
871 }
872 
873 
874 /**
875  * @brief Ethernet MAC transmit interrupt
876  **/
877 
879 {
880  bool_t flag;
881  uint32_t status;
882  uint32_t temp;
884 
885  //Enter interrupt service routine
886  osEnterIsr();
887 
888  //This flag will be set if a higher priority task must be woken
889  flag = FALSE;
890 
891  //Read the TX_STAT register to determine which channels caused the interrupt
893 
894  //Packet transmitted on channel 1?
895  if(status & (1 << CPSW_CH1))
896  {
897  //Point to the buffer descriptor
899 
900  //Read the status flags
901  temp = p->word3 & (CPSW_TX_WORD3_SOP | CPSW_TX_WORD3_EOP |
903 
904  //Misqueued buffer condition?
906  {
907  //Check whether the next descriptor pointer is non-zero
908  if(p->word0 != 0)
909  {
910  //The host corrects the misqueued buffer condition by writing the
911  //misqueued packetís buffer descriptor address to the appropriate
912  //TX DMA head descriptor pointer
913  CPSW_CPDMA_TX_HDP_R(CPSW_CH1) = (uint32_t) p->word0;
914  }
915  }
916 
917  //Write the TX completion pointer
918  CPSW_CPDMA_TX_CP_R(CPSW_CH1) = (uint32_t) p;
919 
920  //Check whether the TX buffer is available for writing
921  if(!(txCurBufferDesc1->word3 & CPSW_TX_WORD3_OWNER))
922  {
923  //Notify the TCP/IP stack that the transmitter is ready to send
924  flag |= osSetEventFromIsr(&nicDriverInterface1->nicTxEvent);
925  }
926  }
927 
928  //Packet transmitted on channel 2?
929  if(status & (1 << CPSW_CH2))
930  {
931  //Point to the buffer descriptor
933 
934  //Read the status flags
935  temp = p->word3 & (CPSW_TX_WORD3_SOP | CPSW_TX_WORD3_EOP |
937 
938  //Misqueued buffer condition?
940  {
941  //Check whether the next descriptor pointer is non-zero
942  if(p->word0 != 0)
943  {
944  //The host corrects the misqueued buffer condition by writing the
945  //misqueued packetís buffer descriptor address to the appropriate
946  //TX DMA head descriptor pointer
947  CPSW_CPDMA_TX_HDP_R(CPSW_CH2) = (uint32_t) p->word0;
948  }
949  }
950 
951  //Write the TX completion pointer
952  CPSW_CPDMA_TX_CP_R(CPSW_CH2) = (uint32_t) p;
953 
954  //Check whether the TX buffer is available for writing
955  if(!(txCurBufferDesc2->word3 & CPSW_TX_WORD3_OWNER))
956  {
957  //Notify the TCP/IP stack that the transmitter is ready to send
958  flag |= osSetEventFromIsr(&nicDriverInterface2->nicTxEvent);
959  }
960  }
961 
962  //Writes the DMA end of interrupt vector
964 
965  //Leave interrupt service routine
966  osExitIsr(flag);
967 }
968 
969 
970 /**
971  * @brief Ethernet MAC receive interrupt
972  **/
973 
975 {
976  bool_t flag;
977  uint32_t status;
978 
979  //Enter interrupt service routine
980  osEnterIsr();
981 
982  //This flag will be set if a higher priority task must be woken
983  flag = FALSE;
984 
985  //Read the RX_STAT register to determine which channels caused the interrupt
987 
988  //Packet received on channel 0?
989  if(status & (1 << CPSW_CH0))
990  {
991  //Disable RX interrupts
993 
994  //Set event flag
995  if(nicDriverInterface1 != NULL)
996  nicDriverInterface1->nicEvent = TRUE;
997  else if(nicDriverInterface2 != NULL)
998  nicDriverInterface2->nicEvent = TRUE;
999 
1000  //Notify the TCP/IP stack of the event
1001  flag |= osSetEventFromIsr(&netEvent);
1002  }
1003 
1004  //Writes the DMA end of interrupt vector
1006 
1007  //Leave interrupt service routine
1008  osExitIsr(flag);
1009 }
1010 
1011 
1012 /**
1013  * @brief AM335x Ethernet MAC event handler
1014  * @param[in] interface Underlying network interface
1015  **/
1016 
1018 {
1019  static uint8_t buffer[AM335X_ETH_RX_BUFFER_SIZE];
1020  error_t error;
1021  size_t n;
1022  uint32_t temp;
1023 
1024  //Process all pending packets
1025  do
1026  {
1027  //The current buffer is available for reading?
1028  if(!(rxCurBufferDesc->word3 & CPSW_RX_WORD3_OWNER))
1029  {
1030  //SOP and EOP flags should be set
1031  if((rxCurBufferDesc->word3 & CPSW_RX_WORD3_SOP) &&
1032  (rxCurBufferDesc->word3 & CPSW_RX_WORD3_EOP))
1033  {
1034  //Make sure no error occurred
1035  if(!(rxCurBufferDesc->word3 & CPSW_RX_WORD3_PKT_ERROR))
1036  {
1037  //Check the port on which the packet was received
1038  switch(rxCurBufferDesc->word3 & CPSW_RX_WORD3_FROM_PORT)
1039  {
1040  //Port 1?
1042  interface = nicDriverInterface1;
1043  break;
1044  //Port 1?
1046  interface = nicDriverInterface2;
1047  break;
1048  //Invalid port number?
1049  default:
1050  interface = NULL;
1051  break;
1052  }
1053 
1054  //Retrieve the length of the frame
1055  n = rxCurBufferDesc->word3 & CPSW_RX_WORD3_PACKET_LENGTH;
1056  //Limit the number of data to read
1058 
1059  //Sanity check
1060  if(interface != NULL)
1061  {
1062  //Copy data from the receive buffer
1063  memcpy(buffer, (uint8_t *) rxCurBufferDesc->word1, (n + 3) & ~3UL);
1064 
1065  //Packet successfully received
1066  error = NO_ERROR;
1067  }
1068  else
1069  {
1070  //The port number is invalid
1071  error = ERROR_INVALID_PACKET;
1072  }
1073  }
1074  else
1075  {
1076  //The received packet contains an error
1077  error = ERROR_INVALID_PACKET;
1078  }
1079  }
1080  else
1081  {
1082  //The packet is not valid
1083  error = ERROR_INVALID_PACKET;
1084  }
1085 
1086  //Mark the end of the queue with a NULL pointer
1087  rxCurBufferDesc->word0 = (uint32_t) NULL;
1088  //Restore the length of the buffer
1089  rxCurBufferDesc->word2 = AM335X_ETH_RX_BUFFER_SIZE;
1090  //Give the ownership of the descriptor back to the DMA
1091  rxCurBufferDesc->word3 = CPSW_RX_WORD3_OWNER;
1092 
1093  //Link the current descriptor to the previous descriptor
1094  rxCurBufferDesc->prev->word0 = (uint32_t) rxCurBufferDesc;
1095 
1096  //Read the status flags of the previous descriptor
1097  temp = rxCurBufferDesc->prev->word3 & (CPSW_RX_WORD3_SOP |
1099 
1100  //Misqueued buffer condition?
1102  {
1103  //The host acts on the misqueued buffer condition by writing the added
1104  //buffer descriptor address to the appropriate RX DMA head descriptor
1105  //pointer
1106  CPSW_CPDMA_RX_HDP_R(CPSW_CH0) = (uint32_t) rxCurBufferDesc;
1107  }
1108 
1109  //Write the RX completion pointer
1110  CPSW_CPDMA_RX_CP_R(CPSW_CH0) = (uint32_t) rxCurBufferDesc;
1111 
1112  //Point to the next descriptor in the list
1113  rxCurBufferDesc = rxCurBufferDesc->next;
1114  }
1115  else
1116  {
1117  //No more data in the receive buffer
1118  error = ERROR_BUFFER_EMPTY;
1119  }
1120 
1121  //Check whether a valid packet has been received
1122  if(!error)
1123  {
1124  //Pass the packet to the upper layer
1125  nicProcessPacket(interface, buffer, n);
1126  }
1127 
1128  //No more data in the receive buffer?
1129  } while(error != ERROR_BUFFER_EMPTY);
1130 
1131  //Re-enable RX interrupts
1133 }
1134 
1135 
1136 /**
1137  * @brief Send a packet (port 1)
1138  * @param[in] interface Underlying network interface
1139  * @param[in] buffer Multi-part buffer containing the data to send
1140  * @param[in] offset Offset to the first data byte
1141  * @return Error code
1142  **/
1143 
1145  const NetBuffer *buffer, size_t offset)
1146 {
1147  static uint8_t temp[AM335X_ETH_TX_BUFFER_SIZE];
1148  size_t length;
1149  uint32_t value;
1150 
1151  //Retrieve the length of the packet
1152  length = netBufferGetLength(buffer) - offset;
1153 
1154  //Check the frame length
1156  {
1157  //The transmitter can accept another packet
1158  osSetEvent(&interface->nicTxEvent);
1159  //Report an error
1160  return ERROR_INVALID_LENGTH;
1161  }
1162 
1163  //Make sure the current buffer is available for writing
1164  if(txCurBufferDesc1->word3 & CPSW_TX_WORD3_OWNER)
1165  return ERROR_FAILURE;
1166 
1167  //Mark the end of the queue with a NULL pointer
1168  txCurBufferDesc1->word0 = (uint32_t) NULL;
1169 
1170  //Copy user data to the transmit buffer
1171  netBufferRead(temp, buffer, offset, length);
1172  memcpy((uint8_t *) txCurBufferDesc1->word1, temp, (length + 3) & ~3UL);
1173 
1174  //Set the length of the buffer
1175  txCurBufferDesc1->word2 = length & CPSW_TX_WORD2_BUFFER_LENGTH;
1176 
1177  //Set the length of the packet
1179  //Set SOP and EOP flags as the data fits in a single buffer
1181  //Redirect the packet to the relevant port number
1183 
1184  //Give the ownership of the descriptor to the DMA
1185  txCurBufferDesc1->word3 = CPSW_TX_WORD3_OWNER | value;
1186 
1187  //Link the current descriptor to the previous descriptor
1188  txCurBufferDesc1->prev->word0 = (uint32_t) txCurBufferDesc1;
1189 
1190  //Read the status flags of the previous descriptor
1191  value = txCurBufferDesc1->prev->word3 & (CPSW_TX_WORD3_SOP |
1193 
1194  //Misqueued buffer condition?
1196  {
1197  //Clear the misqueued buffer condition
1198  txCurBufferDesc1->prev->word3 = 0;
1199 
1200  //The host corrects the misqueued buffer condition by writing the
1201  //misqueued packetís buffer descriptor address to the appropriate
1202  //TX DMA head descriptor pointer
1203  CPSW_CPDMA_TX_HDP_R(CPSW_CH1) = (uint32_t) txCurBufferDesc1;
1204  }
1205 
1206  //Point to the next descriptor in the list
1207  txCurBufferDesc1 = txCurBufferDesc1->next;
1208 
1209  //Check whether the next buffer is available for writing
1210  if(!(txCurBufferDesc1->word3 & CPSW_TX_WORD3_OWNER))
1211  {
1212  //The transmitter can accept another packet
1213  osSetEvent(&interface->nicTxEvent);
1214  }
1215 
1216  //Data successfully written
1217  return NO_ERROR;
1218 }
1219 
1220 
1221 /**
1222  * @brief Send a packet (port 2)
1223  * @param[in] interface Underlying network interface
1224  * @param[in] buffer Multi-part buffer containing the data to send
1225  * @param[in] offset Offset to the first data byte
1226  * @return Error code
1227  **/
1228 
1230  const NetBuffer *buffer, size_t offset)
1231 {
1232  static uint8_t temp[AM335X_ETH_TX_BUFFER_SIZE];
1233  size_t length;
1234  uint32_t value;
1235 
1236  //Retrieve the length of the packet
1237  length = netBufferGetLength(buffer) - offset;
1238 
1239  //Check the frame length
1241  {
1242  //The transmitter can accept another packet
1243  osSetEvent(&interface->nicTxEvent);
1244  //Report an error
1245  return ERROR_INVALID_LENGTH;
1246  }
1247 
1248  //Make sure the current buffer is available for writing
1249  if(txCurBufferDesc2->word3 & CPSW_TX_WORD3_OWNER)
1250  return ERROR_FAILURE;
1251 
1252  //Mark the end of the queue with a NULL pointer
1253  txCurBufferDesc2->word0 = (uint32_t) NULL;
1254 
1255  //Copy user data to the transmit buffer
1256  netBufferRead(temp, buffer, offset, length);
1257  memcpy((uint8_t *) txCurBufferDesc2->word1, temp, (length + 3) & ~3UL);
1258 
1259  //Set the length of the buffer
1260  txCurBufferDesc2->word2 = length & CPSW_TX_WORD2_BUFFER_LENGTH;
1261 
1262  //Set the length of the packet
1264  //Set SOP and EOP flags as the data fits in a single buffer
1266  //Redirect the packet to the relevant port number
1268 
1269  //Give the ownership of the descriptor to the DMA
1270  txCurBufferDesc2->word3 = CPSW_TX_WORD3_OWNER | value;
1271 
1272  //Link the current descriptor to the previous descriptor
1273  txCurBufferDesc2->prev->word0 = (uint32_t) txCurBufferDesc2;
1274 
1275  //Read the status flags of the previous descriptor
1276  value = txCurBufferDesc2->prev->word3 & (CPSW_TX_WORD3_SOP |
1278 
1279  //Misqueued buffer condition?
1281  {
1282  //Clear the misqueued buffer condition
1283  txCurBufferDesc2->prev->word3 = 0;
1284 
1285  //The host corrects the misqueued buffer condition by writing the
1286  //misqueued packetís buffer descriptor address to the appropriate
1287  //TX DMA head descriptor pointer
1288  CPSW_CPDMA_TX_HDP_R(CPSW_CH2) = (uint32_t) txCurBufferDesc2;
1289  }
1290 
1291  //Point to the next descriptor in the list
1292  txCurBufferDesc2 = txCurBufferDesc2->next;
1293 
1294  //Check whether the next buffer is available for writing
1295  if(!(txCurBufferDesc2->word3 & CPSW_TX_WORD3_OWNER))
1296  {
1297  //The transmitter can accept another packet
1298  osSetEvent(&interface->nicTxEvent);
1299  }
1300 
1301  //Data successfully written
1302  return NO_ERROR;
1303 }
1304 
1305 
1306 /**
1307  * @brief Configure MAC address filtering
1308  * @param[in] interface Underlying network interface
1309  * @return Error code
1310  **/
1311 
1313 {
1314  uint_t i;
1315  uint_t port;
1316  MacFilterEntry *entry;
1317 
1318  //Debug message
1319  TRACE_DEBUG("Updating AM335x ALE table...\r\n");
1320 
1321  //Select the relevant port number
1322  if(interface == nicDriverInterface1)
1323  port = CPSW_PORT1;
1324  else if(interface == nicDriverInterface2)
1325  port = CPSW_PORT2;
1326  else
1327  port = CPSW_PORT0;
1328 
1329  //The MAC address filter contains the list of MAC addresses to accept
1330  //when receiving an Ethernet frame
1331  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
1332  {
1333  //Point to the current entry
1334  entry = &interface->macAddrFilter[i];
1335 
1336  //Check whether the ALE table should be updated for the
1337  //current multicast address
1338  if(!macCompAddr(&entry->addr, &MAC_UNSPECIFIED_ADDR))
1339  {
1340  if(entry->addFlag)
1341  {
1342  //Add VLAN/multicast address entry to the ALE table
1344  }
1345  else if(entry->deleteFlag)
1346  {
1347  //Remove VLAN/multicast address entry from the ALE table
1349  }
1350  }
1351  }
1352 
1353  //Successful processing
1354  return NO_ERROR;
1355 }
1356 
1357 
1358 /**
1359  * @brief Adjust MAC configuration parameters for proper operation
1360  * @param[in] interface Underlying network interface
1361  * @return Error code
1362  **/
1363 
1365 {
1366  uint32_t config = 0;
1367 
1368  //Read MAC control register
1369  if(interface == nicDriverInterface1)
1370  config = CPSW_SL1_MACCONTROL_R;
1371  else if(interface == nicDriverInterface2)
1372  config = CPSW_SL2_MACCONTROL_R;
1373 
1374  //1000BASE-T operation mode?
1375  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
1376  {
1377  config |= CPSW_SL_MACCONTROL_GIG;
1378  config &= ~(CPSW_SL_MACCONTROL_IFCTL_A | CPSW_SL_MACCONTROL_IFCTL_B);
1379  }
1380  //100BASE-TX operation mode?
1381  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
1382  {
1383  config &= ~CPSW_SL_MACCONTROL_GIG;
1384  config |= CPSW_SL_MACCONTROL_IFCTL_A | CPSW_SL_MACCONTROL_IFCTL_B;
1385  }
1386  //10BASE-T operation mode?
1387  else
1388  {
1389  config &= ~CPSW_SL_MACCONTROL_GIG;
1390  config &= ~(CPSW_SL_MACCONTROL_IFCTL_A | CPSW_SL_MACCONTROL_IFCTL_B);
1391  }
1392 
1393  //Half-duplex or full-duplex mode?
1394  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
1395  config |= CPSW_SL_MACCONTROL_FULLDUPLEX;
1396  else
1397  config &= ~CPSW_SL_MACCONTROL_FULLDUPLEX;
1398 
1399  //Update MAC control register
1400  if(interface == nicDriverInterface1)
1401  CPSW_SL1_MACCONTROL_R = config;
1402  else if(interface == nicDriverInterface2)
1403  CPSW_SL2_MACCONTROL_R = config;
1404 
1405  //Successful processing
1406  return NO_ERROR;
1407 }
1408 
1409 
1410 /**
1411  * @brief Write PHY register
1412  * @param[in] phyAddr PHY address
1413  * @param[in] regAddr Register address
1414  * @param[in] data Register value
1415  **/
1416 
1417 void am335xEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
1418 {
1419  uint32_t value;
1420 
1421  //Set up a write operation
1422  value = MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE;
1423  //PHY address
1424  value |= (phyAddr << MDIO_USERACCESS0_PHYADR_SHIFT) & MDIO_USERACCESS0_PHYADR;
1425  //Register address
1426  value |= (regAddr << MDIO_USERACCESS0_REGADR_SHIFT) & MDIO_USERACCESS0_REGADR;
1427  //Register value
1428  value |= data & MDIO_USERACCESS0_DATA;
1429 
1430  //Start a write operation
1432  //Wait for the write to complete
1433  while(MDIO_USERACCESS0_R & MDIO_USERACCESS0_GO);
1434 }
1435 
1436 
1437 /**
1438  * @brief Read PHY register
1439  * @param[in] phyAddr PHY address
1440  * @param[in] regAddr Register address
1441  * @return Register value
1442  **/
1443 
1444 uint16_t am335xEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
1445 {
1446  uint32_t value;
1447 
1448  //Set up a read operation
1449  value = MDIO_USERACCESS0_GO | MDIO_USERACCESS0_READ;
1450  //PHY address
1451  value |= (phyAddr << MDIO_USERACCESS0_PHYADR_SHIFT) & MDIO_USERACCESS0_PHYADR;
1452  //Register address
1453  value |= (regAddr << MDIO_USERACCESS0_REGADR_SHIFT) & MDIO_USERACCESS0_REGADR;
1454 
1455  //Start a read operation
1457  //Wait for the read to complete
1458  while(MDIO_USERACCESS0_R & MDIO_USERACCESS0_GO);
1459 
1460  //Return PHY register contents
1461  return MDIO_USERACCESS0_R & MDIO_USERACCESS0_DATA;
1462 }
1463 
1464 
1465 /**
1466  * @brief Write an ALE table entry
1467  * @param[in] index Entry index
1468  * @param[in] entry Pointer to the ALE table entry
1469  **/
1470 
1471 void am335xEthWriteEntry(uint_t index, const Am335xAleEntry *entry)
1472 {
1473  //Copy the content of the entry to be written
1474  CPSW_ALE_TBLW_R(2) = entry->word2;
1475  CPSW_ALE_TBLW_R(1) = entry->word1;
1476  CPSW_ALE_TBLW_R(0) = entry->word0;
1477 
1478  //Write the ALE entry at the specified index
1479  CPSW_ALE_TBLCTL_R = CPSW_ALE_TBLCTL_WRITE_RDZ | index;
1480 }
1481 
1482 
1483 /**
1484  * @brief Read an ALE table entry
1485  * @param[in] index Entry index
1486  * @param[out] entry Pointer to the ALE table entry
1487  **/
1488 
1490 {
1491  //Read the ALE entry at the specified index
1492  CPSW_ALE_TBLCTL_R = index;
1493 
1494  //Copy the content of the entry
1495  entry->word2 = CPSW_ALE_TBLW_R(2);
1496  entry->word1 = CPSW_ALE_TBLW_R(1);
1497  entry->word0 = CPSW_ALE_TBLW_R(0);
1498 }
1499 
1500 
1501 /**
1502  * @brief Find a free entry in the ALE table
1503  * @return Index of the first free entry
1504  **/
1505 
1507 {
1508  uint_t index;
1509  uint32_t type;
1510  Am335xAleEntry entry;
1511 
1512  //Loop through the ALE table entries
1513  for(index = 0; index < CPSW_ALE_MAX_ENTRIES; index++)
1514  {
1515  //Read the current entry
1516  am335xEthReadEntry(index, &entry);
1517 
1518  //Retrieve the type of the ALE entry
1520 
1521  //Free entry?
1523  {
1524  //Exit immediately
1525  break;
1526  }
1527  }
1528 
1529  //Return the index of the entry
1530  return index;
1531 }
1532 
1533 
1534 /**
1535  * @brief Search the ALE table for the specified VLAN entry
1536  * @param[in] vlanId VLAN identifier
1537  * @return Index of the matching entry
1538  **/
1539 
1541 {
1542  uint_t index;
1543  uint32_t value;
1544  Am335xAleEntry entry;
1545 
1546  //Loop through the ALE table entries
1547  for(index = 0; index < CPSW_ALE_MAX_ENTRIES; index++)
1548  {
1549  //Read the current entry
1550  am335xEthReadEntry(index, &entry);
1551 
1552  //Retrieve the type of the ALE entry
1554 
1555  //Check the type of the ALE entry
1557  {
1558  //Get the VLAN identifier
1560 
1561  //Compare the VLAN identifier
1562  if(value == CPSW_ALE_WORD1_VLAN_ID(vlanId))
1563  {
1564  //Matching ALE entry found
1565  break;
1566  }
1567  }
1568  }
1569 
1570  //Return the index of the entry
1571  return index;
1572 }
1573 
1574 
1575 /**
1576  * @brief Search the ALE table for the specified VLAN/address entry
1577  * @param[in] vlanId VLAN identifier
1578  * @param[in] macAddr MAC address
1579  * @return Index of the matching entry
1580  **/
1581 
1583 {
1584  uint_t index;
1585  uint32_t value;
1586  Am335xAleEntry entry;
1587 
1588  //Loop through the ALE table entries
1589  for(index = 0; index < CPSW_ALE_MAX_ENTRIES; index++)
1590  {
1591  //Read the current entry
1592  am335xEthReadEntry(index, &entry);
1593 
1594  //Retrieve the type of the ALE entry
1596 
1597  //Check the type of the ALE entry
1599  {
1600  //Get the VLAN identifier
1602 
1603  //Compare the VLAN identifier
1604  if(value == CPSW_ALE_WORD1_VLAN_ID(vlanId))
1605  {
1606  //Compare the MAC address
1607  if(macAddr->b[0] == (uint8_t) (entry.word1 >> 8) &&
1608  macAddr->b[1] == (uint8_t) (entry.word1 >> 0) &&
1609  macAddr->b[2] == (uint8_t) (entry.word0 >> 24) &&
1610  macAddr->b[3] == (uint8_t) (entry.word0 >> 16) &&
1611  macAddr->b[4] == (uint8_t) (entry.word0 >> 8) &&
1612  macAddr->b[5] == (uint8_t) (entry.word0 >> 0))
1613  {
1614  //Matching ALE entry found
1615  break;
1616  }
1617  }
1618  }
1619  }
1620 
1621  //Return the index of the entry
1622  return index;
1623 }
1624 
1625 
1626 /**
1627  * @brief Add a VLAN entry in the ALE table
1628  * @param[in] port Port number
1629  * @param[in] vlanId VLAN identifier
1630  * @return Error code
1631  **/
1632 
1634 {
1635  error_t error;
1636  uint_t index;
1637  Am335xAleEntry entry;
1638 
1639  //Ensure that there are not duplicate address entries in the ALE table
1640  index = am335xEthFindVlanEntry(vlanId);
1641 
1642  //No matching entry found?
1643  if(index >= CPSW_ALE_MAX_ENTRIES)
1644  {
1645  //Find a free entry in the ALE table
1646  index = am335xEthFindFreeEntry();
1647  }
1648 
1649  //Sanity check
1650  if(index < CPSW_ALE_MAX_ENTRIES)
1651  {
1652  //Set up a VLAN table entry
1653  entry.word2 = 0;
1655  entry.word0 = 0;
1656 
1657  //Set VLAN identifier
1658  entry.word1 |= CPSW_ALE_WORD1_VLAN_ID(vlanId);
1659 
1660  //Force the packet VLAN tag to be removed on egress
1663 
1664  //Set VLAN member list
1665  entry.word0 |= CPSW_ALE_WORD0_VLAN_MEMBER_LIST(1 << port) |
1667 
1668  //Add a new entry to the ALE table
1669  am335xEthWriteEntry(index, &entry);
1670 
1671  //Sucessful processing
1672  error = NO_ERROR;
1673  }
1674  else
1675  {
1676  //The ALE table is full
1677  error = ERROR_FAILURE;
1678  }
1679 
1680  //Return status code
1681  return error;
1682 }
1683 
1684 
1685 /**
1686  * @brief Add a VLAN/address entry in the ALE table
1687  * @param[in] port Port number
1688  * @param[in] vlanId VLAN identifier
1689  * @param[in] macAddr MAC address
1690  * @return Error code
1691  **/
1692 
1694 {
1695  error_t error;
1696  uint_t index;
1697  Am335xAleEntry entry;
1698 
1699  //Ensure that there are not duplicate address entries in the ALE table
1700  index = am335xEthFindVlanAddrEntry(vlanId, macAddr);
1701 
1702  //No matching entry found?
1703  if(index >= CPSW_ALE_MAX_ENTRIES)
1704  {
1705  //Find a free entry in the ALE table
1706  index = am335xEthFindFreeEntry();
1707  }
1708 
1709  //Sanity check
1710  if(index < CPSW_ALE_MAX_ENTRIES)
1711  {
1712  //Set up a VLAN/address table entry
1713  entry.word2 = 0;
1715  entry.word0 = 0;
1716 
1717  //Multicast address?
1718  if(macIsMulticastAddr(macAddr))
1719  {
1720  //Set port mask
1721  entry.word2 |= CPSW_ALE_WORD2_SUPER |
1724 
1725  //Set multicast forward state
1727  }
1728 
1729  //Set VLAN identifier
1730  entry.word1 |= CPSW_ALE_WORD1_VLAN_ID(vlanId);
1731 
1732  //Copy the upper 16 bits of the unicast address
1733  entry.word1 |= (macAddr->b[0] << 8) | macAddr->b[1];
1734 
1735  //Copy the lower 32 bits of the unicast address
1736  entry.word0 |= (macAddr->b[2] << 24) | (macAddr->b[3] << 16) |
1737  (macAddr->b[4] << 8) | macAddr->b[5];
1738 
1739  //Add a new entry to the ALE table
1740  am335xEthWriteEntry(index, &entry);
1741 
1742  //Sucessful processing
1743  error = NO_ERROR;
1744  }
1745  else
1746  {
1747  //The ALE table is full
1748  error = ERROR_FAILURE;
1749  }
1750 
1751  //Return status code
1752  return error;
1753 }
1754 
1755 
1756 /**
1757  * @brief Remove a VLAN/address entry from the ALE table
1758  * @param[in] port Port number
1759  * @param[in] vlanId VLAN identifier
1760  * @param[in] macAddr MAC address
1761  * @return Error code
1762  **/
1763 
1765 {
1766  error_t error;
1767  uint_t index;
1768  Am335xAleEntry entry;
1769 
1770  //Search the ALE table for the specified VLAN/address entry
1771  index = am335xEthFindVlanAddrEntry(vlanId, macAddr);
1772 
1773  //Matching ALE entry found?
1774  if(index < CPSW_ALE_MAX_ENTRIES)
1775  {
1776  //Clear the contents of the entry
1777  entry.word2 = 0;
1778  entry.word1 = 0;
1779  entry.word0 = 0;
1780 
1781  //Update the ALE table
1782  am335xEthWriteEntry(index, &entry);
1783 
1784  //Sucessful processing
1785  error = NO_ERROR;
1786  }
1787  else
1788  {
1789  //Entry not found
1790  error = ERROR_NOT_FOUND;
1791  }
1792 
1793  //Return status code
1794  return error;
1795 }
void am335xEthTick(NetInterface *interface)
AM335x Ethernet MAC timer handler.
void am335xEthInitGpio(NetInterface *interface)
MacAddr addr
MAC address.
Definition: ethernet.h:210
#define CPSW_PORT1_SA_LO_R
#define CPSW_CPDMA_RX_HDP_R(n)
#define CPSW_PORT2
#define CPSW_SL1_SOFT_RESET_R
#define CPSW_RX_WORD3_FROM_PORT_1
#define CPSW_ALE_WORD1_VLAN_ID(n)
#define CPSW_TX_WORD3_TO_PORT_EN
const NicDriver am335xEthPort2Driver
AM335x Ethernet MAC driver (port2)
#define CPSW_TX_WORD3_TO_PORT_1
uint32_t word1
#define CPSW_TX_WORD3_PACKET_LENGTH
#define CPSW_ALE_WORD1_ENTRY_TYPE_FREE
bool_t addFlag
Definition: ethernet.h:212
#define CPSW_PORT0
#define AM335X_ETH_RX_BUFFER_SIZE
#define CONTROL_CONF_MII1_RXERR_R
TCP/IP stack core.
#define CPSW_CPDMA_RX_CONTROL_R
#define CPSW_SS_SOFT_RESET_R
Debugging facilities.
#define CONTROL_CONF_MII1_RXD1_R
uint8_t p
Definition: ndp.h:295
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:295
struct _Am335xRxBufferDesc * prev
#define CPSW_CH0
Generic error code.
Definition: error.h:43
#define CONTROL_CONF_MII1_RXD2_R
#define CPSW_ALE_PORTCTL_R(n)
error_t am335xEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:98
#define CPSW_PORT0_TX_IN_CTL_R
#define CPSW_TX_WORD3_OWNER
error_t am335xEthInitPort1(NetInterface *interface)
AM335x Ethernet MAC initialization (port 1)
#define CONTROL_CONF_MII1_CRS_R
#define CPSW_RX_WORD3_PACKET_LENGTH
bool_t deleteFlag
Definition: ethernet.h:213
#define AM335X_ETH_IRQ_PRIORITY
#define MDIO_USERACCESS0_R
void am335xEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
error_t am335xEthDeleteVlanAddrEntry(uint_t port, uint_t vlanId, MacAddr *macAddr)
Remove a VLAN/address entry from the ALE table.
TX buffer descriptor.
#define AM335X_ETH_RX_BUFFER_COUNT
#define CPSW_ALE_WORD0_VLAN_MEMBER_LIST(n)
uint32_t word2
#define CPSW_SS_STAT_PORT_EN_R
#define CPSW_ALE_WORD1_ENTRY_TYPE_VLAN_ADDR
#define CONTROL_CONF_MII1_TXD3_R
error_t am335xEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
char_t type
#define CONTROL_CONF_MII1_TXCLK_R
#define CONTROL_CONF_MDIO_DATA_R
error_t am335xEthSendPacketPort2(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet (port 2)
#define CONTROL_CONF_MII1_TXD2_R
struct _Am335xTxBufferDesc * prev
#define CPSW_SL2_MACCONTROL_R
#define CONTROL_GMII_SEL_GMII1_SEL_MII
#define CM_PER_CPGMAC0_CLKCTRL_R
#define CPSW_ALE_PORTCTL_PORT_STATE_FORWARD
RX buffer descriptor.
#define CPSW_CPDMA_TX_CONTROL_R
void am335xEthInitInstance(NetInterface *interface)
Initialize CPSW instance.
#define CPSW_WR_SOFT_RESET_R
#define CPSW_ALE_CONTROL_R
#define CPSW_CPDMA_TX_HDP_R(n)
#define CPSW_CH2
#define TRUE
Definition: os_port.h:48
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:65
#define CPSW_TX_WORD3_EOQ
#define CPSW_ALE_TBLCTL_R
uint16_t am335xEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define CPSW_TX_WORD3_EOP
#define CONTROL_CONF_MII1_COL_R
void am335xEthEventHandler(NetInterface *interface)
AM335x Ethernet MAC event handler.
#define CPSW_CPDMA_EOI_VECTOR_TX_PULSE
error_t am335xEthAddVlanEntry(uint_t port, uint_t vlanId)
Add a VLAN entry in the ALE table.
const NicDriver am335xEthPort1Driver
AM335x Ethernet MAC driver (port1)
#define CPSW_RX_WORD3_FROM_PORT_2
uint_t am335xEthFindFreeEntry(void)
Find a free entry in the ALE table.
#define CPSW_ALE_WORD1_ENTRY_TYPE_MASK
#define CONTROL_GMII_SEL_GMII1_SEL_RMII
#define CM_PER_CPSW_CLKSTCTRL_R
#define CPSW_WR_C_RX_EN_R(n)
#define CONTROL_CONF_MII1_TXD0_R
ALE table entry.
#define CPSW_CORE0
struct _Am335xRxBufferDesc * next
void am335xEthDisableIrq(NetInterface *interface)
Disable interrupts.
#define MDIO_CONTROL_R
#define CPSW_CPDMA_EOI_VECTOR_RX_PULSE
#define CPSW_SL2_SOFT_RESET_R
#define CPSW_ALE_WORD1_VLAN_ID_MASK
#define CONTROL_CONF_MII1_TXD1_R
void am335xEthEnableIrq(NetInterface *interface)
Enable interrupts.
uint_t am335xEthFindVlanAddrEntry(uint_t vlanId, MacAddr *macAddr)
Search the ALE table for the specified VLAN/address entry.
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:670
#define CPSW_TX_WORD3_TO_PORT_2
#define CONTROL_MAC_ID_HI_R(n)
struct _Am335xTxBufferDesc * next
void am335xEthReadEntry(uint_t index, Am335xAleEntry *entry)
Read an ALE table entry.
#define CONTROL_CONF_RMII1_REFCLK_R
#define CONTROL_CONF_GPMC_A_R(n)
NIC driver.
Definition: nic.h:161
#define CPSW_CPDMA_CPDMA_SOFT_RESET_R
#define CPSW_CPDMA_RX_INTMASK_SET_R
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
#define MIN(a, b)
Definition: os_port.h:60
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define CPSW_PORT1_SA_HI_R
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
#define CPSW_CH1
#define CPSW_CPDMA_TX_INTMASK_SET_R
void am335xEthRxIrqHandler(void)
Ethernet MAC receive interrupt.
#define CONTROL_GMII_SEL_GMII1_SEL_RGMII
void macAddrToEui64(const MacAddr *macAddr, Eui64 *interfaceId)
Map a MAC address to the IPv6 modified EUI-64 identifier.
Definition: ethernet.c:1266
#define CPSW_WR_C_RX_STAT_R(n)
#define CPSW_PORT1
#define TRACE_INFO(...)
Definition: debug.h:86
#define CPSW_CH7
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:82
#define CONTROL_CONF_MDIO_CLK_R
Ethernet interface.
Definition: nic.h:69
Success.
Definition: error.h:42
#define AM335X_ETH_TX_BUFFER_COUNT
#define rxBuffer
#define CPSW_ALE_WORD2_PORT_LIST(n)
#define CPSW_ALE_WORD1_ENTRY_TYPE_VLAN
#define CPSW_PORT2_SA_LO_R
#define CONTROL_CONF_MII1_TXEN_R
OsEvent netEvent
Definition: net.c:72
void am335xEthTxIrqHandler(void)
Ethernet MAC transmit interrupt.
void nicProcessPacket(NetInterface *interface, void *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:239
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
error_t
Error codes.
Definition: error.h:40
#define CPSW_CPDMA_TX_CP_R(n)
#define CPSW_RX_WORD3_FROM_PORT
#define MDIO_OUTPUT_CLK
uint32_t word0
#define CPSW_SL1_MACCONTROL_R
#define CONTROL_GMII_SEL_GMII2_SEL_RGMII
error_t am335xEthAddVlanAddrEntry(uint_t port, uint_t vlanId, MacAddr *macAddr)
Add a VLAN/address entry in the ALE table.
unsigned int uint_t
Definition: compiler_port.h:43
Sitara AM335x Ethernet MAC controller.
__start_packed struct @112 MacAddr
MAC address.
uint8_t data[]
Definition: dtls_misc.h:167
#define NetInterface
Definition: net.h:34
#define CPSW_ALE_WORD1_MCAST_FWD_STATE(n)
#define CPSW_ALE_TBLW_R(n)
uint8_t value[]
Definition: dtls_misc.h:141
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:95
#define AM335X_ETH_TX_BUFFER_SIZE
#define CONTROL_CONF_MII1_RXDV_R
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
#define CONTROL_CONF_MII1_RXD0_R
#define CPSW_RX_WORD3_EOP
uint16_t port
Definition: dns_common.h:221
#define CPSW_RX_WORD3_SOP
#define CONTROL_GMII_SEL_R
#define CONTROL_MAC_ID_LO_R(n)
#define CPSW_RX_WORD3_PKT_ERROR
void am335xEthWriteEntry(uint_t index, const Am335xAleEntry *entry)
Write an ALE table entry.
#define CPSW_TX_WORD3_SOP
#define MDIO_INPUT_CLK
#define osExitIsr(flag)
#define CPSW_PORT2_SA_HI_R
#define CPSW_RX_WORD3_EOQ
#define CPSW_RX_WORD3_OWNER
#define CPSW_CPDMA_CPDMA_EOI_VECTOR_R
#define osEnterIsr()
uint_t am335xEthFindVlanEntry(uint_t vlanId)
Search the ALE table for the specified VLAN entry.
#define CONTROL_CONF_MII1_RXD3_R
#define CPSW_PORT2_PORT_VLAN_R
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
#define CONTROL_CONF_MII1_RXCLK_R
#define CPSW_WR_C_TX_EN_R(n)
#define FALSE
Definition: os_port.h:44
#define CPSW_ALE_WORD2_SUPER
#define CPSW_WR_C_TX_STAT_R(n)
int bool_t
Definition: compiler_port.h:47
error_t am335xEthSendPacketPort1(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet (port 1)
#define CPSW_ALE_WORD0_FORCE_UNTAG_EGRESS(n)
#define CPSW_ALE_MAX_ENTRIES
#define CPSW_CPDMA_RX_CP_R(n)
#define CPSW_TX_WORD2_BUFFER_LENGTH
MAC filter table entry.
Definition: ethernet.h:208
void am335xEthInitBufferDesc(NetInterface *interface)
Initialize buffer descriptor lists.
#define CPSW_PORT1_PORT_VLAN_R
#define TRACE_DEBUG(...)
Definition: debug.h:98
error_t am335xEthInitPort2(NetInterface *interface)
AM335x Ethernet MAC initialization (port 2)