1 /*******************************************************************************
2  * Copyright 2020 Microchip Corporation.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * PolarFire SoC 10/100/1000 Mbps Ethernet MAC bare metal software driver implementation.
7  *
8  */
9 #include <stdint.h>
10 #include <stdbool.h>
11 #include <stddef.h>
12 #include <string.h>
13 #include "mpfs_hal/mss_hal.h"
14 
15 #if defined(MSS_MAC_PHY_HW_RESET) || defined(MSS_MAC_PHY_HW_SRESET)
16 #include "drivers/mss_gpio/mss_gpio.h"
17 #endif
18 
19 #include "drivers/mss_ethernet_mac/mss_ethernet_registers.h"
20 #include "drivers/mss_ethernet_mac/mss_ethernet_mac_regs.h"
21 #include "drivers/mss_ethernet_mac/mss_ethernet_mac_sw_cfg.h"
22 
23 #if defined(USING_FREERTOS)
24 #include "FreeRTOS.h"
25 #endif
26 
27 #include "drivers/mss_ethernet_mac/mss_ethernet_mac.h"
28 #include "drivers/mss_ethernet_mac/phy.h"
29 #include "hal/hal.h"
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 #if (defined(MSS_MAC_VSC8662_NWC_25) || defined(MSS_MAC_VSC8662_NWC_125))
36 
37 extern PLL_TypeDef *MSS_SCB_MSS_PLL;
38 extern  PLL_TypeDef *MSS_SCB_DDR_PLL;
39 extern  PLL_TypeDef *MSS_SCB_SGMII_PLL;
40 extern IOSCB_CFM_MSS *MSS_SCB_CFM_MSS_MUX;
41 extern IOSCB_CFM_SGMII *MSS_SCB_CFM_SGMII_MUX;
42 extern IOSCB_IO_CALIB_STRUCT *IOSCB_IO_CALIB_SGMII;
43 extern  IOSCB_IO_CALIB_STRUCT *IOSCB_IO_CALIB_DDR;
44 
45 #endif
46 
47 /**************************************************************************/
48 /* Preprocessor Macros                                                    */
49 /**************************************************************************/
50 
51 #define NULL_POINTER                    (void *)0U
52 
53 #if !defined(NDEBUG)
54 #define IS_STATE(x)                     ( ((x) == MSS_MAC_ENABLE) || ((x) == MSS_MAC_DISABLE) )
55 
56 #endif  /* NDEBUG */
57 
58 #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
59 #define IS_WORD_ALIGNED(x)              ((uint64_t)0U == ((uint64_t)(x) & (uint64_t)3U))
60 #else
61 #define IS_WORD_ALIGNED(x)              ((uint32_t)0U == ((uint32_t)(x) & (uint32_t)3U))
62 #endif
63 
64 #define BMSR_AUTO_NEGOTIATION_COMPLETE  (0x0020U)
65 
66 #define INVALID_INDEX                   (0xFFFFFFFFU)
67 
68 #define PHY_ADDRESS_MIN                 (0U)
69 #define PHY_ADDRESS_MAX                 (31U)
70 
71 /*
72  * Defines for determining DMA descriptor sizes
73  */
74 #if 0
75  #if !defined(MSS_MAC_TIME_STAMPED_MODE)
76 #define MSS_MAC_TIME_STAMPED_MODE      0 /* Default to non time stamped descriptors */
77 #endif
78 #endif
79 
80 #if defined(TARGET_ALOE)
81 #define MSS_MAC0_BASE     (0x10090000U);
82 #elif defined(TARGET_G5_SOC)
83 #define MSS_MAC0_BASE     (0x20110000U)
84 #define MSS_EMAC0_BASE    (0x20111000U)
85 #define MSS_MAC1_BASE     (0x20112000U)
86 #define MSS_EMAC1_BASE    (0x20113000U)
87 
88 #define MSS_MAC0_BASE_HI  (0x28110000U)
89 #define MSS_EMAC0_BASE_HI (0x28111000U)
90 #define MSS_MAC1_BASE_HI  (0x28112000U)
91 #define MSS_EMAC1_BASE_HI (0x28113000U)
92 
93 #define MSS_MAC_GEM0_ABP_BIT (0x00010000U)
94 #define MSS_MAC_GEM1_ABP_BIT (0x00020000U)
95 #else
96 #warning "No target platform defined for MSS Ethernet MAC"
97 #endif
98 
99 /**************************************************************************/
100 /* Private variables                                                      */
101 /**************************************************************************/
102 
103 #if defined(TARGET_ALOE)
104 static volatile uint32_t *GEMGXL_tx_clk_sel = (volatile uint32_t *)0x100A0000UL;
105 static volatile uint32_t *GEMGXL_speed_mode = (volatile uint32_t *)0x100A0020UL;
106 #endif
107 
108 /**************************************************************************
109  * Global variables                                                       *
110  *                                                                        *
111  * Note: there are two instances of the GMAC for G5 SOC and each has a    *
112  * primary MAC and a secondary eMAC for time sensative traffic. The FU540 *
113  * device on the Aloe board has a single primary MAC.                     *
114  **************************************************************************/
115 
116 #if defined(TARGET_G5_SOC)
117 mss_mac_instance_t g_mac0;
118 mss_mac_instance_t g_mac1;
119 mss_mac_instance_t g_emac0;
120 mss_mac_instance_t g_emac1;
121 #endif
122 
123 #if defined(MSS_MAC_USE_DDR)
124 #if MSS_MAC_USE_DDR == MSS_MAC_MEM_DDR
125 uint8_t *g_mss_mac_ddr_ptr = (uint8_t *)0xC0000000LLU;
126 #elif MSS_MAC_USE_DDR == MSS_MAC_MEM_FIC0
127 uint8_t *g_mss_mac_ddr_ptr = (uint8_t *)0x60000000LLU;
128 #elif MSS_MAC_USE_DDR == MSS_MAC_MEM_FIC1
129 uint8_t *g_mss_mac_ddr_ptr = (uint8_t *)0xE0000000LLU;
130 #elif MSS_MAC_USE_DDR == MSS_MAC_MEM_CRYPTO
131 uint8_t *g_mss_mac_ddr_ptr = (uint8_t *)0x22002000LLU;
132 #else
133 #error "bad memory region defined"
134 #endif
135 #endif
136 
137 
138 #if defined(TARGET_ALOE)
139 mss_mac_instance_t g_mac0;
140 #endif
141 
142 
143 /**************************************************************************/
144 /* Private Functions                                                      */
145 /**************************************************************************/
146 static void mac_reset(void);
147 static void config_mac_hw(mss_mac_instance_t *this_mac, const mss_mac_cfg_t * cfg);
148 static void tx_desc_ring_init(mss_mac_instance_t *this_mac);
149 static void rx_desc_ring_init(mss_mac_instance_t *this_mac);
150 static void assign_station_addr(mss_mac_instance_t *this_mac, const uint8_t mac_addr[MSS_MAC_MAC_LEN]);
151 static void generic_mac_irq_handler(mss_mac_instance_t *this_mac, uint64_t queue_no);
152 static void rxpkt_handler(mss_mac_instance_t *this_mac, uint64_t queue_no);
153 static void txpkt_handler(mss_mac_instance_t *this_mac, uint64_t queue_no);
154 static void update_mac_cfg(const mss_mac_instance_t *this_mac);
155 static uint8_t probe_phy(const mss_mac_instance_t *this_mac);
156 static void instances_init(mss_mac_instance_t *this_mac, mss_mac_cfg_t *cfg);
157 
158 static void msgmii_init(const mss_mac_instance_t *this_mac);
159 
160 /* PMCS: Made non static for now for test program use... */
161 void msgmii_autonegotiate(const mss_mac_instance_t *this_mac);
162 
163 /**************************************************************************/
164 /* Public Functions                                                       */
165 /**************************************************************************/
166 /******************************************************************************
167  * See mss_ethernet_mac.h for details of how to use this function.
168  */
169 void
MSS_MAC_init(mss_mac_instance_t * this_mac,mss_mac_cfg_t * cfg)170 MSS_MAC_init
171 (
172     mss_mac_instance_t *this_mac,
173     mss_mac_cfg_t      *cfg
174 )
175 {
176     int32_t queue_no;
177     ASSERT(cfg != NULL_POINTER);
178 #if defined(TARGET_ALOE)
179     ASSERT(this_mac == &g_mac0);
180 
181     instances_init(this_mac, cfg);
182 
183     if((cfg != NULL_POINTER) && (this_mac == &g_mac0))
184 #endif
185 #if defined(TARGET_G5_SOC)
186     ASSERT((this_mac == &g_mac0) || (this_mac == &g_mac1) || (this_mac == &g_emac0) || (this_mac == &g_emac1));
187     instances_init(this_mac, cfg);
188 
189     /*
190      * Always reset GEM if the pMAC is selected for init but not if eMAC
191      * The pMAC should always be initialised first followed by the eMAC so this
192      * is ok...
193      */
194     if(this_mac == &g_mac0)
195     {
196         SYSREG->SUBBLK_CLOCK_CR |= (uint32_t)2U;
197         /* Reset MAC */
198         SYSREG->SOFT_RESET_CR |= (uint32_t)2U;
199         {
200             volatile int64_t index;
201 
202             index = 0;
203             while(1000 != index) /* Don't know if necessary, but delay a bit before de-asserting reset... */
204             {
205                 index++;
206             }
207         }
208         /* Take MAC out of reset. */
209         SYSREG->SOFT_RESET_CR &= (uint32_t)~2U;
210     }
211 
212     if(this_mac == &g_mac1)
213     {
214         SYSREG->SUBBLK_CLOCK_CR |= (uint32_t)4U;
215         /* Reset MAC */
216         SYSREG->SOFT_RESET_CR |= (uint32_t)4U;
217         {
218             volatile int64_t index;
219 
220             index = 0;
221             while(1000 != index) /* Don't know if necessary, but delay a bit before de-asserting reset... */
222             {
223                 index++;
224             }
225         }
226         /* Take MAC out of reset. */
227         SYSREG->SOFT_RESET_CR &= (uint32_t)~4U;
228     }
229 
230     /*
231      * Disable all queues.
232      *
233      * In theory you only need to write 1UL to the queue pointers but in
234      * practice doing this results in spurious accesses to addresses in the
235      * lower 4K on the AXI bus when enabling a queue which can trigger hresp
236      * errors. To stop this we use real addresses with the lsb set instead.
237      */
238     if(0U == this_mac->is_emac)
239     {
240         *this_mac->queue[0].receive_q_ptr  = (uint32_t)((uint64_t)this_mac->queue[0].rx_desc_tab) | 1U;
241         *this_mac->queue[1].receive_q_ptr  = (uint32_t)((uint64_t)this_mac->queue[1].rx_desc_tab) | 1U;
242         *this_mac->queue[2].receive_q_ptr  = (uint32_t)((uint64_t)this_mac->queue[2].rx_desc_tab) | 1U;
243         *this_mac->queue[3].receive_q_ptr  = (uint32_t)((uint64_t)this_mac->queue[3].rx_desc_tab) | 1U;
244         *this_mac->queue[0].transmit_q_ptr = (uint32_t)((uint64_t)this_mac->queue[0].tx_desc_tab) | 1U;
245         *this_mac->queue[1].transmit_q_ptr = (uint32_t)((uint64_t)this_mac->queue[1].tx_desc_tab) | 1U;
246         *this_mac->queue[2].transmit_q_ptr = (uint32_t)((uint64_t)this_mac->queue[2].tx_desc_tab) | 1U;
247         *this_mac->queue[3].transmit_q_ptr = (uint32_t)((uint64_t)this_mac->queue[3].tx_desc_tab) | 1U;
248     }
249     else
250     {
251         *this_mac->queue[0].receive_q_ptr  = (uint32_t)((uint64_t)this_mac->queue[0].rx_desc_tab) | 1U;
252         *this_mac->queue[0].transmit_q_ptr = (uint32_t)((uint64_t)this_mac->queue[0].tx_desc_tab) | 1U;
253     }
254 
255     if(0U == this_mac->is_emac)
256     {
257         this_mac->mac_base->USER_IO = cfg->tsu_clock_select & 1U;
258     }
259 
260     if((cfg != NULL_POINTER) && ((this_mac == &g_mac0) || (this_mac == &g_mac1) || (this_mac == &g_emac0) || (this_mac == &g_emac1)))
261 #endif /* defined(TARGET_G5_SOC) */
262     {
263         this_mac->phy_addr              = cfg->phy_addr;
264         this_mac->pcs_phy_addr          = cfg->pcs_phy_addr;
265         this_mac->interface_type        = cfg->interface_type;
266         this_mac->jumbo_frame_enable    = cfg->jumbo_frame_enable;
267         this_mac->phy_type              = cfg->phy_type;
268         this_mac->phy_autonegotiate     = cfg->phy_autonegotiate;
269         this_mac->phy_mac_autonegotiate = cfg->phy_mac_autonegotiate;
270         this_mac->phy_get_link_status   = cfg->phy_get_link_status;
271         this_mac->phy_init              = cfg->phy_init;
272         this_mac->phy_set_link_speed    = cfg->phy_set_link_speed;
273         this_mac->append_CRC            = cfg->append_CRC;
274 #if defined(MSS_MAC_PHY_HW_RESET) || defined(MSS_MAC_PHY_HW_SRESET)
275         this_mac->phy_soft_reset_gpio   = cfg->phy_soft_reset_gpio;
276         this_mac->phy_soft_reset_pin    = cfg->phy_soft_reset_pin;
277         this_mac->phy_hard_reset_gpio   = cfg->phy_hard_reset_gpio;
278         this_mac->phy_hard_reset_pin    = cfg->phy_hard_reset_pin;
279 #endif
280         this_mac->phy_controller        = cfg->phy_controller;
281         this_mac->speed_mode            = cfg->speed_mode;
282         this_mac->speed_duplex_select   = cfg->speed_duplex_select;
283 #if MSS_MAC_USE_PHY_DP83867
284         this_mac->phy_extended_read     = cfg->phy_extended_read;
285         this_mac->phy_extended_write    = cfg->phy_extended_write;
286 #endif
287 
288 #if defined(TARGET_G5_SOC)
289         if(0U != cfg->use_local_ints)
290         {
291             __disable_local_irq(this_mac->mac_q_int[0]);
292             if(0U == this_mac->is_emac)
293             {
294                 __disable_local_irq(this_mac->mac_q_int[1]);
295                 __disable_local_irq(this_mac->mac_q_int[2]);
296                 __disable_local_irq(this_mac->mac_q_int[3]);
297                 __disable_local_irq(this_mac->mmsl_int);
298             }
299         }
300         else
301 #endif
302         {
303             /*
304              * In the following if an interrupt is set to NoInterrupt_IRQn then
305              * the PLIC will ignore it as interrupt 0 is a dummy one.
306              */
307             PLIC_DisableIRQ(this_mac->mac_q_int[0]);
308             PLIC_SetPriority(this_mac->mac_q_int[0], cfg->queue0_int_priority);
309 
310 #if defined(TARGET_G5_SOC)
311             PLIC_DisableIRQ(this_mac->mac_q_int[1]);
312             PLIC_SetPriority(this_mac->mac_q_int[1], cfg->queue1_int_priority);
313             PLIC_DisableIRQ(this_mac->mac_q_int[2]);
314             PLIC_SetPriority(this_mac->mac_q_int[2], cfg->queue2_int_priority);
315             PLIC_DisableIRQ(this_mac->mac_q_int[3]);
316             PLIC_SetPriority(this_mac->mac_q_int[3], cfg->queue3_int_priority);
317             PLIC_DisableIRQ(this_mac->mmsl_int);
318             PLIC_SetPriority(this_mac->mmsl_int, cfg->mmsl_int_priority);
319 #endif
320         }
321         mac_reset();
322 
323         config_mac_hw(this_mac, cfg);
324 
325         /* Assign MAC station address */
326         assign_station_addr(this_mac, cfg->mac_addr);
327 
328         /* Intialize Tx & Rx descriptor rings */
329         tx_desc_ring_init(this_mac);
330         rx_desc_ring_init(this_mac);
331 
332         this_mac->rx_discard = 0U; /* Ensure normal RX operation */
333 
334         for(queue_no = 0; queue_no < MSS_MAC_QUEUE_COUNT; queue_no++)
335         {
336             /* Initialize Tx descriptors related variables. */
337             this_mac->queue[queue_no].nb_available_tx_desc    = MSS_MAC_TX_RING_SIZE;
338 
339             /* Initialize Rx descriptors related variables. */
340             this_mac->queue[queue_no].nb_available_rx_desc    = MSS_MAC_RX_RING_SIZE;
341             this_mac->queue[queue_no].next_free_rx_desc_index = 0U;
342             this_mac->queue[queue_no].first_rx_desc_index     = 0U;
343 
344             /* initialize default interrupt handlers */
345             this_mac->queue[queue_no].pckt_tx_callback        = (mss_mac_transmit_callback_t)NULL_POINTER;
346             this_mac->queue[queue_no].pckt_rx_callback        = (mss_mac_receive_callback_t)NULL_POINTER;
347 
348             /* Added these to MAC structure to make them MAC and queue specific... */
349 
350             this_mac->queue[queue_no].ingress     = 0U;
351             this_mac->queue[queue_no].egress      = 0U;
352             this_mac->queue[queue_no].rx_overflow = 0U;
353             this_mac->queue[queue_no].hresp_error = 0U;
354             this_mac->queue[queue_no].rx_restart  = 0U;
355             this_mac->queue[queue_no].tx_restart  = 0U;
356             this_mac->queue[queue_no].tx_reenable = 0U;
357         }
358 #if 0
359         /* Initialize PHY interface */
360         if(MSS_MAC_AUTO_DETECT_PHY_ADDRESS == cfg->phy_addr)
361         {
362             cfg->phy_addr = probe_phy();
363         }
364 #endif
365     if(0U == this_mac->is_emac) /* Only do the PHY stuff for primary MAC */
366         {
367             if(TBI == this_mac->interface_type)
368             {
369                 msgmii_init(this_mac);
370             }
371 #if defined(TARGET_ALOE)
372             this_mac->phy_addr = 0U;
373 #endif
374 
375             this_mac->phy_init(this_mac, (uint8_t)this_mac->phy_addr);
376 
377 #if (defined(MSS_MAC_VSC8662_NWC_25) || defined(MSS_MAC_VSC8662_NWC_125))
378             /* 0U => configure using scb, 1U => NVMAP reset */
379                 pre_configure_sgmii_and_ddr_pll_via_scb(1U);
380             {
381                 volatile uint32_t timer_out=0x00000FFFU;
382                 while(((MSS_SCB_SGMII_PLL->PLL_CTRL & ((0x01U) << 25U))) == 0U)
383                 {
384                 #ifdef RENODE_DEBUG
385                     break;
386                 #endif
387                     if (timer_out == 0U)
388                     {
389                         timer_out--;
390                     }
391                 }
392             }
393 
394 #endif
395             this_mac->phy_set_link_speed(this_mac, this_mac->speed_duplex_select, this_mac->speed_mode);
396             this_mac->phy_autonegotiate(this_mac);
397 
398             if(TBI == this_mac->interface_type)
399             {
400                 msgmii_autonegotiate(this_mac);
401             }
402         }
403         update_mac_cfg(this_mac);
404 
405         /*
406          * Enable TX Packet and TX Packet Bus Error interrupts.
407          * We don't enable the tx underrun interrupt as we only send on demand
408          * and don't need to explicitly note an underrun as that is the "normal"
409          * state for the interface to be in.
410          */
411         /*
412          * Enable RX Packet, RX Packet Overflow and RX Packet Bus Error
413          * interrupts.
414          */
415         if(0U != this_mac->is_emac)
416         {
417             this_mac->emac_base->INT_ENABLE = GEM_RECEIVE_OVERRUN_INT | GEM_TRANSMIT_COMPLETE |
418                                               GEM_RX_USED_BIT_READ | GEM_RECEIVE_COMPLETE | GEM_RESP_NOT_OK_INT;
419 
420             this_mac->emac_base->NETWORK_CONTROL |= GEM_ENABLE_TRANSMIT;
421             this_mac->emac_base->NETWORK_CONTROL |= GEM_TRANSMIT_START;
422 
423         }
424         else
425         {
426             for(queue_no = 0; queue_no < MSS_MAC_QUEUE_COUNT; queue_no++)
427             {
428                 /* Enable pause related interrupts if pause control is selected */
429                 if((MSS_MAC_ENABLE == cfg->rx_flow_ctrl) || (MSS_MAC_ENABLE == cfg->tx_flow_ctrl))
430                 {
431                     *this_mac->queue[queue_no].int_enable = GEM_RECEIVE_OVERRUN_INT | GEM_TRANSMIT_COMPLETE |
432                             GEM_RX_USED_BIT_READ | GEM_RECEIVE_COMPLETE | GEM_RESP_NOT_OK_INT |
433                             GEM_PAUSE_FRAME_TRANSMITTED | GEM_PAUSE_TIME_ELAPSED |
434                             GEM_PAUSE_FRAME_WITH_NON_0_PAUSE_QUANTUM_RX | GEM_AMBA_ERROR;
435                 }
436                 else
437                 {
438                     *this_mac->queue[queue_no].int_enable = GEM_RECEIVE_OVERRUN_INT | GEM_TRANSMIT_COMPLETE |
439                             GEM_RX_USED_BIT_READ | GEM_RECEIVE_COMPLETE | GEM_RESP_NOT_OK_INT;
440                 }
441 
442 #if 0 /* PMCS - set this to 1 if you want to check for un-handled interrupt conditions */
443                 *this_mac->queue[queue_no].int_enable |= GEM_PAUSE_FRAME_TRANSMITTED | GEM_PAUSE_TIME_ELAPSED |
444                         GEM_PAUSE_FRAME_WITH_NON_0_PAUSE_QUANTUM_RX | GEM_LINK_CHANGE |
445                         GEM_TX_LOCKUP_DETECTED | GEM_RX_LOCKUP_DETECTED |
446                         GEM_AMBA_ERROR  | GEM_RETRY_LIMIT_EXCEEDED_OR_LATE_COLLISION |
447                         GEM_TRANSMIT_UNDER_RUN;
448 #endif
449             }
450 
451             this_mac->mac_base->NETWORK_CONTROL |= GEM_ENABLE_TRANSMIT;
452             this_mac->mac_base->NETWORK_CONTROL |= GEM_TRANSMIT_START;
453         }
454 
455         /*
456          * At this stage, the MSS MAC interrupts are disabled and won't be enabled
457          * until at least one of the FIFOs is configured with a buffer(s) for
458          * data transfer.
459          */
460     }
461 
462     this_mac->mac_available = MSS_MAC_AVAILABLE;
463 }
464 
465 
466 /******************************************************************************
467  * See mss_ethernet_mac.h for details of how to use this function.
468  */
469 void
MSS_MAC_update_hw_address(mss_mac_instance_t * this_mac,const mss_mac_cfg_t * cfg)470 MSS_MAC_update_hw_address
471 (
472     mss_mac_instance_t *this_mac,
473     const mss_mac_cfg_t * cfg
474 )
475 {
476     ASSERT(cfg != NULL_POINTER);
477 
478     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
479     {
480         if(cfg != NULL_POINTER)
481         {
482             /* Assign MAC station address */
483             assign_station_addr(this_mac, cfg->mac_addr);
484         }
485     }
486 }
487 
488 
489 /******************************************************************************
490  *
491  */
update_mac_cfg(const mss_mac_instance_t * this_mac)492 static void update_mac_cfg(const mss_mac_instance_t *this_mac)
493 {
494     mss_mac_speed_t speed;
495     uint8_t fullduplex;
496     uint8_t link_up;
497     uint32_t temp_cr;
498 
499     link_up = this_mac->phy_get_link_status(this_mac, &speed, &fullduplex);
500 
501     if(link_up != MSS_MAC_LINK_DOWN)
502     {
503         if(0U != this_mac->is_emac)
504         {
505             temp_cr = this_mac->emac_base->NETWORK_CONFIG;
506         }
507         else
508         {
509             temp_cr = this_mac->mac_base->NETWORK_CONFIG;
510         }
511 
512         temp_cr &= ~(GEM_GIGABIT_MODE_ENABLE | GEM_SPEED | GEM_FULL_DUPLEX);
513 
514         if(MSS_MAC_1000MBPS == speed)
515         {
516 #if defined(TARGET_ALOE)
517             *GEMGXL_tx_clk_sel = (uint32_t)0U;
518             *GEMGXL_speed_mode = (uint32_t)2U;
519 #endif
520             temp_cr |= GEM_GIGABIT_MODE_ENABLE;
521         }
522         else
523         {
524             if(MSS_MAC_100MBPS == speed)
525             {
526 #if defined(TARGET_ALOE)
527                 *GEMGXL_tx_clk_sel = (uint32_t)1U;
528                 *GEMGXL_speed_mode = (uint32_t)1U;
529 #endif
530                 temp_cr |= (uint32_t)GEM_SPEED;
531             }
532 #if defined(TARGET_ALOE)
533             else
534             {
535                 *GEMGXL_tx_clk_sel = (uint32_t)1U;
536                 *GEMGXL_speed_mode = (uint32_t)0U;
537             }
538 #endif
539         }
540         /* Configure duplex mode */
541         if(MSS_MAC_FULL_DUPLEX == fullduplex)
542         {
543             temp_cr |= GEM_FULL_DUPLEX;
544         }
545 
546         if(0U != this_mac->is_emac)
547         {
548             this_mac->emac_base->NETWORK_CONFIG = temp_cr;
549         }
550         else
551         {
552             this_mac->mac_base->NETWORK_CONFIG = temp_cr;
553         }
554     }
555 }
556 
557 
558 /******************************************************************************
559  * See mss_ethernet_mac.h for details of how to use this function.
560  */
MSS_MAC_get_link_status(const mss_mac_instance_t * this_mac,mss_mac_speed_t * speed,uint8_t * fullduplex)561 uint8_t MSS_MAC_get_link_status
562 (
563     const mss_mac_instance_t *this_mac,
564     mss_mac_speed_t * speed,
565     uint8_t *     fullduplex
566 )
567 {
568     /* Todo: These statics will only work for the single MAC Aloe case... */
569     static mss_mac_speed_t previous_speed = INVALID_SPEED;
570     static uint8_t previous_duplex = 0xAAU;
571     mss_mac_speed_t link_speed;
572     uint8_t link_fullduplex;
573     uint8_t link_up;
574 
575     link_up = MSS_MAC_LINK_DOWN; /* Default condition in case we are not active yet */
576 
577     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
578     {
579         link_up = this_mac->phy_get_link_status(this_mac, &link_speed, &link_fullduplex);
580 
581         if(link_up != MSS_MAC_LINK_DOWN)
582         {
583             /*----------------------------------------------------------------------
584              * Update MAC configuration if link characteristics changed.
585              */
586             if((link_speed != previous_speed) || (link_fullduplex != previous_duplex))
587             {
588                 uint32_t temp_cr;
589 
590                 if(0U != this_mac->is_emac)
591                 {
592                     temp_cr = this_mac->emac_base->NETWORK_CONFIG;
593                 }
594                 else
595                 {
596                     temp_cr = this_mac->mac_base->NETWORK_CONFIG;
597                 }
598 
599                 temp_cr &= ~(GEM_GIGABIT_MODE_ENABLE | GEM_SPEED | GEM_FULL_DUPLEX);
600 
601                 if(MSS_MAC_1000MBPS == link_speed)
602                 {
603     #if defined(TARGET_ALOE)
604                     *GEMGXL_tx_clk_sel = (uint32_t)0U;
605                     *GEMGXL_speed_mode = (uint32_t)2U;
606     #endif
607                     temp_cr |= GEM_GIGABIT_MODE_ENABLE;
608                 }
609                 else
610                 {
611                     if(MSS_MAC_100MBPS == link_speed)
612                     {
613     #if defined(TARGET_ALOE)
614                         *GEMGXL_tx_clk_sel = (uint32_t)1U;
615                         *GEMGXL_speed_mode = (uint32_t)1U;
616     #endif
617                         temp_cr |= (uint32_t)GEM_SPEED;
618                     }
619     #if defined(TARGET_ALOE)
620                     else
621                     {
622                         *GEMGXL_tx_clk_sel = (uint32_t)1U;
623                         *GEMGXL_speed_mode = (uint32_t)0U;
624                     }
625     #endif
626                 }
627                 /* Configure duplex mode */
628                 if(MSS_MAC_FULL_DUPLEX == link_fullduplex)
629                 {
630                     temp_cr |= GEM_FULL_DUPLEX;
631                 }
632 
633                 if(0U != this_mac->is_emac)
634                 {
635                     this_mac->emac_base->NETWORK_CONFIG = temp_cr;
636                 }
637                 else
638                 {
639                     this_mac->mac_base->NETWORK_CONFIG = temp_cr;
640                 }
641             }
642 
643             previous_speed = link_speed;
644             previous_duplex = link_fullduplex;
645 
646             /*----------------------------------------------------------------------
647              * Return current link speed and duplex mode.
648              */
649             if(speed != NULL_POINTER)
650             {
651                 *speed = link_speed;
652             }
653 
654             if(fullduplex != NULL_POINTER)
655             {
656                 *fullduplex = link_fullduplex;
657             }
658             if(GMII_SGMII == this_mac->interface_type) /* Emulation platform with embedded SGMII link for PHY connection and GMII for MAC connection */
659             {
660                 uint16_t phy_reg;
661                 uint16_t sgmii_link_up;
662 
663                 /*
664                  * Find out if link is up on SGMII link between GMII core and
665                  * external PHY.
666                  *
667                  * The link status bit latches 0 state until read to record fact
668                  * link has failed since last read so you need to read it twice to
669                  * get the current status...
670                  */
671                 phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->pcs_phy_addr, MII_BMSR);
672                 phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->pcs_phy_addr, MII_BMSR);
673                 sgmii_link_up = phy_reg & BMSR_LSTATUS;
674 
675                 if(0U == sgmii_link_up)
676                 {
677                     /* Initiate auto-negotiation on the SGMII link. */
678                     phy_reg = MSS_MAC_read_phy_reg(this_mac, (uint8_t)this_mac->pcs_phy_addr, MII_BMCR);
679                     phy_reg |= BMCR_ANENABLE;
680                     MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->pcs_phy_addr, MII_BMCR, phy_reg);
681                     phy_reg |= BMCR_ANRESTART;
682                     MSS_MAC_write_phy_reg(this_mac, (uint8_t)this_mac->pcs_phy_addr, MII_BMCR, phy_reg);
683                 }
684              }
685 
686 #if 0 /* TBD old SF2 stuff keep here for now for guidance... */
687 #if ((MSS_MAC_PHY_INTERFACE == SGMII) || (MSS_MAC_PHY_INTERFACE == TBI))
688 #if (MSS_MAC_PHY_INTERFACE == TBI)
689 /*----------------------------------------------------------------------
690  * Make sure SGMII interface link is up. if interface is TBI
691  */
692 #define MDIO_PHY_ADDR   SF2_MSGMII_PHY_ADDR
693 #endif /* #if (MSS_MAC_PHY_INTERFACE == TBI) */
694 
695 #if (MSS_MAC_PHY_INTERFACE == SGMII)
696 /*----------------------------------------------------------------------
697  * Make sure SGMII/1000baseX interface link is up. if interface is
698  * SGMII/1000baseX
699  */
700 #define MDIO_PHY_ADDR   MSS_MAC_INTERFACE_MDIO_ADDR
701 #endif /* #if ((MSS_MAC_PHY_INTERFACE == SGMII) || (MSS_MAC_PHY_INTERFACE == BASEX1000)) */
702 
703         {
704             uint16_t phy_reg;
705             uint16_t sgmii_link_up;
706 
707             /* Find out if link is up on SGMII link between MAC and external PHY. */
708             phy_reg = MSS_MAC_read_phy_reg(MDIO_PHY_ADDR, MII_BMSR);
709             sgmii_link_up = phy_reg & BMSR_LSTATUS;
710 
711             if(0U == sgmii_link_up)
712             {
713                 /* Initiate auto-negotiation on the SGMII link. */
714                 phy_reg = MSS_MAC_read_phy_reg(MDIO_PHY_ADDR, MII_BMCR);
715                 phy_reg |= BMCR_ANENABLE;
716                 MSS_MAC_write_phy_reg(MDIO_PHY_ADDR, MII_BMCR, phy_reg);
717                 phy_reg |= BMCR_ANRESTART;
718                 MSS_MAC_write_phy_reg(MDIO_PHY_ADDR, MII_BMCR, phy_reg);
719             }
720          }
721 #endif
722 #endif
723         }
724     }
725 
726     return link_up;
727 }
728 
729 
730 /******************************************************************************
731  * See mss_ethernet_mac.h for details of how to use this function.
732  */
733 void
MSS_MAC_cfg_struct_def_init(mss_mac_cfg_t * cfg)734 MSS_MAC_cfg_struct_def_init
735 (
736     mss_mac_cfg_t * cfg
737 )
738 {
739     ASSERT(NULL_POINTER != cfg);
740     if(NULL_POINTER != cfg)
741     {
742         (void)memset(cfg, 0, sizeof(mss_mac_cfg_t)); /* Start with clean slate */
743 
744         cfg->speed_duplex_select   = MSS_MAC_ANEG_ALL_SPEEDS;
745         cfg->speed_mode            = MSS_MAC_SPEED_AN;
746 #if defined(TARGET_ALOE)
747         cfg->phy_addr              = 0U;
748 #endif
749 #if defined(MSS_MAC_PHY_HW_RESET) || defined(MSS_MAC_PHY_HW_SRESET)
750         cfg->phy_addr              = PHY_NULL_MDIO_ADDR;
751         cfg->phy_soft_reset_gpio   = (GPIO_TypeDef *)0UL;
752         cfg->phy_soft_reset_pin    = MSS_GPIO_0;
753         cfg->phy_hard_reset_gpio   = (GPIO_TypeDef *)0UL;
754         cfg->phy_hard_reset_pin    = MSS_GPIO_0;
755 #endif
756         cfg->phy_controller        = (mss_mac_instance_t *)0UL;
757         cfg->tx_edc_enable         = MSS_MAC_ERR_DET_CORR_DISABLE;
758         cfg->rx_edc_enable         = MSS_MAC_ERR_DET_CORR_DISABLE;
759         cfg->jumbo_frame_enable    = MSS_MAC_JUMBO_FRAME_DISABLE;
760         cfg->jumbo_frame_default   = MSS_MAC_MAX_PACKET_SIZE;
761         cfg->length_field_check    = MSS_MAC_LENGTH_FIELD_CHECK_ENABLE;
762         cfg->append_CRC            = MSS_MAC_CRC_ENABLE;
763         cfg->loopback              = MSS_MAC_LOOPBACK_DISABLE;
764         cfg->rx_flow_ctrl          = MSS_MAC_RX_FLOW_CTRL_ENABLE;
765         cfg->tx_flow_ctrl          = MSS_MAC_TX_FLOW_CTRL_ENABLE;
766         cfg->ipg_multiplier        = MSS_MAC_IPG_DEFVAL;
767         cfg->ipg_divisor           = MSS_MAC_IPG_DEFVAL;
768         cfg->phyclk                = MSS_MAC_DEF_PHY_CLK;
769         cfg->mac_addr[0]           = 0x00U;
770         cfg->mac_addr[1]           = 0x00U;
771         cfg->mac_addr[2]           = 0x00U;
772         cfg->mac_addr[3]           = 0x00U;
773         cfg->mac_addr[4]           = 0x00U;
774         cfg->mac_addr[5]           = 0x00U;
775         cfg->queue_enable[0]       = MSS_MAC_QUEUE_DISABLE;
776         cfg->queue_enable[1]       = MSS_MAC_QUEUE_DISABLE;
777         cfg->queue_enable[2]       = MSS_MAC_QUEUE_DISABLE;
778         cfg->queue_enable[3]       = MSS_MAC_QUEUE_DISABLE;
779         cfg->phy_type              = MSS_MAC_DEV_PHY_NULL;
780         cfg->interface_type        = NULL_PHY;
781         cfg->phy_autonegotiate     = MSS_MAC_NULL_phy_autonegotiate;
782         cfg->phy_mac_autonegotiate = MSS_MAC_NULL_phy_mac_autonegotiate;
783         cfg->phy_get_link_status   = MSS_MAC_NULL_phy_get_link_status;
784         cfg->phy_init              = MSS_MAC_NULL_phy_init;
785         cfg->phy_set_link_speed    = MSS_MAC_NULL_phy_set_link_speed;
786         cfg->use_hi_address        = MSS_MAC_DISABLE;
787         cfg->use_local_ints        = MSS_MAC_DISABLE;
788         cfg->queue0_int_priority   = 7U; /* Give them highest priority by default */
789         cfg->queue1_int_priority   = 7U;
790         cfg->queue2_int_priority   = 7U;
791         cfg->queue3_int_priority   = 7U;
792         cfg->mmsl_int_priority     = 7U;
793         /*
794          * PMCS: Note for the Emulation platform we need to select the non
795          * default TSU clock the moment or TX won't work
796          */
797         cfg->tsu_clock_select      = 0U;
798         cfg->amba_burst_length     = MSS_MAC_AMBA_BURST_16;
799 
800 #if MSS_MAC_USE_PHY_DP83867
801         cfg->phy_extended_read     = NULL_ti_read_extended_regs;
802         cfg->phy_extended_write    = NULL_ti_write_extended_regs;
803 #endif
804     }
805 }
806 
807 
808 /******************************************************************************
809  *
810  */
811 static void
mac_reset(void)812 mac_reset
813 (
814     void
815 )
816 {
817 }
818 
819 #if defined(TARGET_ALOE)
820 
821 /******************************************************************************
822  * PLL and Reset registers after reset in "wait for debug mode"
823  * 0x10000000 : 0x10000000 <Hex Integer>
824  * Address   0 - 3     4 - 7     8 - B     C - F
825  * 10000000  C0000000  030187C1  00000000  030187C1
826  * 10000010  00000000  00000000  00000000  030187C1
827  * 10000020  00000000  00000001  00000000  00000004
828  *
829  * PLL and Reset registers after Linux boot.
830  *
831  * 0x10000000 : 0x10000000 <Hex Integer>
832  * Address   0 - 3     4 - 7     8 - B     C - F
833  * 10000000  C0000000  82110EC0  00000000  82110DC0
834  * 10000010  80000000  00000000  00000000  82128EC0
835  * 10000020  80000000  00000000  0000002F  00000004
836  *
837  */
838 
839 /******************************************************************************
840  *
841  */
842 #define __I  const volatile
843 #define __IO volatile
844 #define __O volatile
845 
846 typedef struct
847 {
848     __IO uint32_t  HFXOSCCFG;      /* 0x0000 */
849     __IO uint32_t  COREPLLCFG0;    /* 0x0004 */
850     __IO uint32_t  reserved0;      /* 0x0008 */
851     __IO uint32_t  DDRPLLCFG0;     /* 0x000C */
852     __IO uint32_t  DDRPLLCFG1;     /* 0x0010 */
853     __IO uint32_t  reserved1;      /* 0x0014 */
854     __IO uint32_t  reserved2;      /* 0x0018 */
855     __IO uint32_t  GEMGXLPLLCFG0;  /* 0x001C */
856     __IO uint32_t  GEMGXLPLLCFG1;  /* 0x0020 */
857     __IO uint32_t  CORECLKSEL;     /* 0x0024 */
858     __IO uint32_t  DEVICERESETREG; /* 0x0028 */
859 } AloePRCI_TypeDef;
860 
861 AloePRCI_TypeDef *g_aloe_prci = (AloePRCI_TypeDef *)0x10000000UL;
862 
863 typedef struct
864 {
865     __IO uint32_t  PWMCFG;         /* 0x0000 */
866     __IO uint32_t  reserved0;      /* 0x0004 */
867     __IO uint32_t  PWMCOUNT;       /* 0x0008 */
868     __IO uint32_t  reserved1;      /* 0x000C */
869     __IO uint32_t  PWMS;           /* 0x0010 */
870     __IO uint32_t  reserved2;      /* 0x0014 */
871     __IO uint32_t  reserved3;      /* 0x0018 */
872     __IO uint32_t  reserved4;      /* 0x001C */
873     __IO uint32_t  PWMCMP0;        /* 0x0020 */
874     __IO uint32_t  PWMCMP1;        /* 0x0024 */
875     __IO uint32_t  PWMCMP2;        /* 0x0028 */
876     __IO uint32_t  PWMCMP3;        /* 0x002C */
877 } AloePWM_TypeDef;
878 
879 AloePWM_TypeDef *g_aloe_pwm0 = (AloePWM_TypeDef *)0x10020000UL;
880 
881 
882 static void config_mac_pll_and_reset(void);
config_mac_pll_and_reset(void)883 static void config_mac_pll_and_reset(void)
884 {
885     volatile int64_t ix;
886     volatile int64_t counter;
887     volatile int64_t loops = 0;
888 
889     /*
890      * COREPLLCFG0 reset value = 0x030187C1
891      *  divr = 1
892      *  divf = 1F
893      *  divq = 3
894      *  range = 0
895      *  bypass = 1
896      *  fse = 1
897      *  lock = 0
898      *
899      *  Desired value = 82110EC0
900      *  divr = 0
901      *  divf = 1D
902      *  divq = 2
903      *  range = 4
904      *  bypass = 0
905      *  fse = 1
906      *  lock = 1
907      */
908 #if 0 /* Test code for proving Core clock speed switching works */
909     g_aloe_pwm0->PWMCFG = 0x0000020EU;
910     g_aloe_pwm0->PWMCMP0 = 0x0000FFFFU;
911     g_aloe_pwm0->PWMCMP1 = 0x0000FFFFU;
912     g_aloe_pwm0->PWMCMP2 = 0x0000FFFFU;
913     g_aloe_pwm0->PWMCMP3 = 0x0000FFFFU;
914 
915     while(loops < 16)
916     {
917         if(ix & 1)
918         {
919             g_aloe_pwm0->PWMCMP0 = 0x00000000U;
920         }
921         else
922         {
923             g_aloe_pwm0->PWMCMP0 = 0x0000FFFFU;
924         }
925 
926         if(ix & 2)
927         {
928             g_aloe_pwm0->PWMCMP1 = 0x00000000U;
929         }
930         else
931         {
932             g_aloe_pwm0->PWMCMP1 = 0x0000FFFFU;
933         }
934 
935         if(ix & 4)
936         {
937             g_aloe_pwm0->PWMCMP2 = 0x00000000U;
938         }
939         else
940         {
941             g_aloe_pwm0->PWMCMP2 = 0x0000FFFFU;
942         }
943 
944         if(ix & 8)
945         {
946             g_aloe_pwm0->PWMCMP3 = 0x00000000U;
947         }
948         else
949         {
950             g_aloe_pwm0->PWMCMP3 = 0x0000FFFFU;
951         }
952 
953         ix++;
954         for(counter = 0; counter != 100000; counter++)
955             ;
956 
957         loops++;
958     }
959 #endif
960 
961     g_aloe_prci->COREPLLCFG0 = 0x03110EC0U; /* Configure Core Clock PLL */
962     while(g_aloe_prci->COREPLLCFG0 & 0x80000000U) /* Wait for lock with PLL bypassed */
963         ix++;
964 
965     g_aloe_prci->COREPLLCFG0 = 0x02110EC0U; /* Take PLL out of bypass */
966     g_aloe_prci->CORECLKSEL  = 0x00000000U; /* Switch to PLL as clock source */
967 
968 #if 0 /* Test code for proving Core clock speed switching works */
969     loops = 0;
970     while(loops < 20)
971     {
972         if(ix & 1)
973         {
974             g_aloe_pwm0->PWMCMP0 = 0x0000FFFFU;
975         }
976         else
977         {
978             g_aloe_pwm0->PWMCMP0 = 0x00000000U;
979         }
980 
981         ix++;
982         for(counter = 0; counter != 3000000; counter++)
983             ;
984 
985         loops++;
986     }
987 #endif
988     /*
989      * GEMGXLPLLCFG0 reset value = 0x030187C1
990      *  divr = 1
991      *  divf = 1F
992      *  divq = 3
993      *  range = 0
994      *  bypass = 1
995      *  fse = 1
996      *  lock = 0
997      *
998      *  Desired value = 82128EC0
999      *  divr = 0
1000      *  divf = 3B
1001      *  divq = 5
1002      *  range = 4
1003      *  bypass = 0
1004      *  fse = 1
1005      *  lock = 1
1006      */
1007 
1008     g_aloe_prci->GEMGXLPLLCFG0 = 0x03128EC0U; /* Configure GEM Clock PLL */
1009     while(g_aloe_prci->GEMGXLPLLCFG0 & 0x80000000U) /* Wait for lock with PLL bypassed */
1010         ix++;
1011 
1012     g_aloe_prci->GEMGXLPLLCFG0 = 0x02128EC0U; /* Take PLL out of bypass */
1013     g_aloe_prci->GEMGXLPLLCFG1  = 0x80000000U; /* Switch to PLL as clock source */
1014 
1015     g_aloe_prci->DEVICERESETREG |= 0x00000020U; /* Release MAC from reset */
1016 
1017 }
1018 #endif
1019 
1020 
1021 /******************************************************************************
1022  *
1023  */
config_mac_hw(mss_mac_instance_t * this_mac,const mss_mac_cfg_t * cfg)1024 static void config_mac_hw(mss_mac_instance_t *this_mac, const mss_mac_cfg_t * cfg)
1025 {
1026     uint32_t temp_net_config = 0U;
1027     uint32_t temp_net_control = 0U;
1028     uint32_t temp_dma_config = 0U;
1029     uint32_t temp_length;
1030 
1031     /* Check for validity of configuration parameters */
1032     ASSERT( IS_STATE(cfg->tx_edc_enable) );
1033     ASSERT( IS_STATE(cfg->rx_edc_enable) );
1034     ASSERT( IS_STATE(cfg->jumbo_frame_enable) );
1035     ASSERT( IS_STATE(cfg->length_field_check) );
1036     ASSERT( IS_STATE(cfg->append_CRC) );
1037     ASSERT( IS_STATE(cfg->loopback) );
1038     ASSERT( IS_STATE(cfg->rx_flow_ctrl) );
1039     ASSERT( IS_STATE(cfg->tx_flow_ctrl) );
1040 
1041 #if defined(TARGET_ALOE)
1042     config_mac_pll_and_reset();
1043 #endif
1044     /*--------------------------------------------------------------------------
1045      * Configure MAC Network Control register
1046      */
1047 /*    temp_net_control = GEM_MAN_PORT_EN | GEM_CLEAR_ALL_STATS_REGS | GEM_PFC_ENABLE; */
1048     temp_net_control = GEM_MAN_PORT_EN | GEM_CLEAR_ALL_STATS_REGS | GEM_PFC_ENABLE | GEM_ALT_SGMII_MODE;
1049 #if 0
1050     temp_net_control |= GEM_LOOPBACK_LOCAL; /* PMCS: Enable this to force local loop back */
1051 #endif
1052     if(MSS_MAC_ENABLE == cfg->loopback)
1053     {
1054         temp_net_control |= GEM_LOOPBACK_LOCAL;
1055     }
1056 
1057 #if defined(MSS_MAC_TIME_STAMPED_MODE)
1058     temp_net_control |= GEM_PTP_UNICAST_ENA;
1059 #endif
1060 
1061     /*
1062      *  eMAC has to be configured as external TSU although it is actually using
1063      *  the pMAC TSU. There is only really 1 TSU per GEM instance and all
1064      *  adjustments etc should really be done via the pMAC.
1065      */
1066     if(0U != this_mac->is_emac)
1067     {
1068         temp_net_control |= GEM_EXT_TSU_PORT_ENABLE;
1069     }
1070     /*--------------------------------------------------------------------------
1071      * Configure MAC Network Config and Network Control registers
1072      */
1073 
1074 #if defined(TARGET_G5_SOC)
1075     if(TBI == this_mac->interface_type)
1076     {
1077         temp_net_config = (((uint32_t)(1UL)) << GEM_DATA_BUS_WIDTH_SHIFT) | ((cfg->phyclk & GEM_MDC_CLOCK_DIVISOR_MASK) << GEM_MDC_CLOCK_DIVISOR_SHIFT) | GEM_PCS_SELECT | GEM_SGMII_MODE_ENABLE;
1078     }
1079     else
1080     {
1081         /* Actually for the G5 SoC Emulation Platform the interface is GMII... */
1082         temp_net_config = (((uint32_t)(1UL)) << GEM_DATA_BUS_WIDTH_SHIFT) | ((cfg->phyclk & GEM_MDC_CLOCK_DIVISOR_MASK) << GEM_MDC_CLOCK_DIVISOR_SHIFT);
1083     }
1084 #endif
1085 #if defined(TARGET_ALOE)
1086     /* No pause frames received in memory, divide PCLK by 224 for MDC */
1087     temp_net_config = (cfg->phyclk & GEM_MDC_CLOCK_DIVISOR_MASK) << GEM_MDC_CLOCK_DIVISOR_SHIFT;
1088 #endif
1089 
1090     if((MSS_MAC_ENABLE == cfg->rx_flow_ctrl) || (MSS_MAC_ENABLE == cfg->tx_flow_ctrl))
1091     {
1092         temp_net_config |= GEM_FCS_REMOVE | GEM_DISABLE_COPY_OF_PAUSE_FRAMES | GEM_RECEIVE_1536_BYTE_FRAMES | GEM_PAUSE_ENABLE | GEM_FULL_DUPLEX | GEM_GIGABIT_MODE_ENABLE;
1093     }
1094     else
1095     {
1096         temp_net_config |= GEM_FCS_REMOVE | GEM_DISABLE_COPY_OF_PAUSE_FRAMES | GEM_RECEIVE_1536_BYTE_FRAMES | GEM_FULL_DUPLEX | GEM_GIGABIT_MODE_ENABLE;
1097     }
1098 
1099     if(MSS_MAC_ENABLE == cfg->length_field_check)
1100     {
1101         temp_net_config |= GEM_LENGTH_FIELD_ERROR_FRAME_DISCARD;
1102     }
1103 
1104     if(MSS_MAC_IPG_DEFVAL != cfg->ipg_multiplier) /* If we have a non zero value here then enable IPG stretching */
1105     {
1106         uint32_t stretch;
1107         temp_net_config |= GEM_IPG_STRETCH_ENABLE;
1108 
1109         stretch  = cfg->ipg_multiplier & GEM_IPG_STRETCH_MUL_MASK;
1110         stretch |= (cfg->ipg_divisor & GEM_IPG_STRETCH_DIV_MASK) << GEM_IPG_STRETCH_DIV_SHIFT;
1111 
1112         if(0U != this_mac->is_emac)
1113         {
1114             this_mac->emac_base->STRETCH_RATIO = stretch;
1115         }
1116         else
1117         {
1118             this_mac->mac_base->STRETCH_RATIO = stretch;
1119         }
1120     }
1121 
1122     if(0U != this_mac->is_emac)
1123     {
1124         this_mac->emac_base->NETWORK_CONTROL = temp_net_control;
1125         this_mac->emac_base->NETWORK_CONFIG  = temp_net_config;
1126         this_mac->mac_base->NETWORK_CONFIG   = temp_net_config;
1127     }
1128     else
1129     {
1130         this_mac->mac_base->NETWORK_CONTROL  = temp_net_control;
1131         this_mac->mac_base->NETWORK_CONFIG   = temp_net_config;
1132 #if defined(TARGET_G5_SOC)
1133         this_mac->emac_base->NETWORK_CONFIG  = temp_net_config;
1134 #endif
1135     }
1136 
1137     /*--------------------------------------------------------------------------
1138      * Reset PCS
1139      */
1140     if(0U == this_mac->is_emac)
1141     {
1142         this_mac->mac_base->PCS_CONTROL |= (uint32_t)0x8000UL;
1143     }
1144 
1145     /*--------------------------------------------------------------------------
1146      * Configure MAC Network DMA Config register
1147      */
1148 
1149     temp_dma_config =  (MSS_MAC_RX_BUF_VALUE << GEM_RX_BUF_SIZE_SHIFT) |
1150                        GEM_TX_PBUF_SIZE |
1151                        (((uint32_t)(0x3UL)) << GEM_RX_PBUF_SIZE_SHIFT) |
1152                        ((uint32_t)(cfg->amba_burst_length & MSS_MAC_AMBA_BURST_MASK));
1153 
1154 #if defined(MSS_MAC_TIME_STAMPED_MODE)
1155     temp_dma_config |= GEM_TX_BD_EXTENDED_MODE_EN | GEM_RX_BD_EXTENDED_MODE_EN;
1156 #endif
1157 
1158 #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
1159     temp_dma_config |= GEM_DMA_ADDR_BUS_WIDTH_1;
1160 #endif
1161 
1162 if(0U != this_mac->is_emac)
1163     {
1164     this_mac->emac_base->DMA_CONFIG = temp_dma_config;
1165 
1166 #if defined(MSS_MAC_TIME_STAMPED_MODE)
1167         /* Record TS for all packets by default */
1168         this_mac->emac_base->TX_BD_CONTROL = GEM_BD_TS_MODE;
1169         this_mac->emac_base->RX_BD_CONTROL = GEM_BD_TS_MODE;
1170 #endif
1171     }
1172     else
1173     {
1174         int32_t queue_index;
1175         this_mac->mac_base->DMA_CONFIG = temp_dma_config;
1176 #if defined(MSS_MAC_TIME_STAMPED_MODE)
1177         /* Record TS for all packets by default */
1178         this_mac->mac_base->TX_BD_CONTROL = GEM_BD_TS_MODE;
1179         this_mac->mac_base->RX_BD_CONTROL = GEM_BD_TS_MODE;
1180 #endif
1181 #if (MSS_MAC_QUEUE_COUNT > 1)
1182         for(queue_index = 1; queue_index < MSS_MAC_QUEUE_COUNT; queue_index++)
1183         {
1184             *(this_mac->queue[queue_index].dma_rxbuf_size) = ((uint32_t)MSS_MAC_RX_BUF_VALUE);
1185         }
1186 #endif
1187     }
1188 
1189     /*
1190      * Disable the other queues as the GEM reset leaves them enabled with an
1191      * address pointer of 0 for some unfathomable reason... This screws things
1192      * up when we enable transmission or reception.
1193      *
1194      * Setting b0 of the queue pointer disables a queue.
1195      */
1196 #if (MSS_MAC_QUEUE_COUNT > 1)
1197     if(0U == this_mac->is_emac)
1198     {     /* Added these to MAC structure to make them MAC specific... */
1199         this_mac->mac_base->TRANSMIT_Q1_PTR = ((uint32_t)(uint64_t)this_mac->queue[0].tx_desc_tab) | 1U; /* Use address of valid descriptor but set b0 to disable */
1200         this_mac->mac_base->TRANSMIT_Q2_PTR = ((uint32_t)(uint64_t)this_mac->queue[0].tx_desc_tab) | 1U;
1201         this_mac->mac_base->TRANSMIT_Q3_PTR = ((uint32_t)(uint64_t)this_mac->queue[0].tx_desc_tab) | 1U;
1202         this_mac->mac_base->RECEIVE_Q1_PTR  = ((uint32_t)(uint64_t)this_mac->queue[0].rx_desc_tab) | 1U;
1203         this_mac->mac_base->RECEIVE_Q2_PTR  = ((uint32_t)(uint64_t)this_mac->queue[0].rx_desc_tab) | 1U;
1204         this_mac->mac_base->RECEIVE_Q3_PTR  = ((uint32_t)(uint64_t)this_mac->queue[0].rx_desc_tab) | 1U;
1205     }
1206 #endif
1207 
1208     /* Set up maximum initial jumbo frame size - but bounds check first  */
1209     if(cfg->jumbo_frame_default > MSS_MAC_JUMBO_MAX)
1210     {
1211         temp_length = MSS_MAC_JUMBO_MAX;
1212     }
1213     else
1214     {
1215         temp_length = cfg->jumbo_frame_default;
1216     }
1217 
1218     if(0U != this_mac->is_emac)
1219     {
1220         this_mac->emac_base->JUMBO_MAX_LENGTH = temp_length;
1221     }
1222     else
1223     {
1224         this_mac->mac_base->JUMBO_MAX_LENGTH = temp_length;
1225     }
1226 
1227     /*--------------------------------------------------------------------------
1228      * Disable all ints for now
1229      */
1230     if(0U != this_mac->is_emac)
1231     {
1232         this_mac->emac_base->INT_DISABLE = ((uint32_t)0xFFFFFFFFUL); /* Only one queue here... */
1233     }
1234     else
1235     {
1236         int32_t queue_no;
1237         for(queue_no = 0; queue_no < MSS_MAC_QUEUE_COUNT; queue_no++)
1238         {
1239             *(this_mac->queue[queue_no].int_disable) = ((uint32_t)0xFFFFFFFFUL);
1240         }
1241     }
1242 
1243 }
1244 
1245 
1246 /******************************************************************************
1247  * See mss_ethernet_mac.h for details of how to use this function.
1248  */
1249 void
MSS_MAC_write_phy_reg(const mss_mac_instance_t * this_mac_in,uint8_t phyaddr,uint8_t regaddr,uint16_t regval)1250 MSS_MAC_write_phy_reg
1251 (
1252     const mss_mac_instance_t *this_mac_in,
1253     uint8_t phyaddr,
1254     uint8_t regaddr,
1255     uint16_t regval
1256 )
1257 {
1258     volatile uint32_t phy_op;
1259     psr_t lev;
1260     const mss_mac_instance_t *this_mac;
1261 
1262     ASSERT(MSS_MAC_PHYADDR_MAXVAL >= phyaddr);
1263     ASSERT(MSS_MAC_PHYREGADDR_MAXVAL >= regaddr);
1264 
1265     /* Check to see which MAC is actually in charge of PHY interface */
1266     if((struct mss_mac_instance *)0UL != this_mac_in->phy_controller)
1267     {
1268         this_mac = (const mss_mac_instance_t *)this_mac_in->phy_controller;
1269     }
1270     else
1271     {
1272         this_mac = this_mac_in;
1273     }
1274 
1275     /*
1276      * Write PHY address in MII Mgmt address register.
1277      * Makes previous register address 0 & invalid.
1278      *
1279      * Don't check mac_available flag here as we may be called in the MAC init
1280      * phase before everything else is in place...
1281      */
1282     if((MSS_MAC_PHYADDR_MAXVAL >= phyaddr) &&
1283        (MSS_MAC_PHYREGADDR_MAXVAL >= regaddr))
1284     {
1285         phy_op = GEM_WRITE1 | (GEM_PHY_OP_CL22_WRITE << GEM_OPERATION_SHIFT) | (((uint32_t)(2UL)) << GEM_WRITE10_SHIFT) | (uint32_t)regval;
1286         phy_op |= ((uint32_t)phyaddr << GEM_PHY_ADDRESS_SHIFT) & GEM_PHY_ADDRESS;
1287         phy_op |= ((uint32_t)regaddr << GEM_REGISTER_ADDRESS_SHIFT) & GEM_REGISTER_ADDRESS;
1288 
1289         lev = HAL_disable_interrupts();
1290         /*
1291          * Always use the pMAC for this as the eMAC MDIO interface is not
1292          * connected to the outside world...
1293          */
1294         /* Wait for MII Mgmt interface to complete previous operation. */
1295         do
1296         {
1297             volatile int32_t ix;
1298             ix++;
1299         } while(0U == (this_mac->mac_base->NETWORK_STATUS & GEM_MAN_DONE));
1300 
1301         this_mac->mac_base->PHY_MANAGEMENT = phy_op;
1302         HAL_restore_interrupts(lev);
1303     }
1304 }
1305 
1306 
1307 
1308 
1309 /******************************************************************************
1310  * See mss_ethernet_mac.h for details of how to use this function.
1311  */
1312 uint16_t
MSS_MAC_read_phy_reg(const mss_mac_instance_t * this_mac_in,uint8_t phyaddr,uint8_t regaddr)1313 MSS_MAC_read_phy_reg
1314 (
1315     const mss_mac_instance_t *this_mac_in,
1316     uint8_t phyaddr,
1317     uint8_t regaddr
1318 )
1319 {
1320     volatile uint32_t phy_op;
1321     psr_t lev;
1322     const mss_mac_instance_t *this_mac;
1323 
1324     ASSERT(MSS_MAC_PHYADDR_MAXVAL >= phyaddr);
1325     ASSERT(MSS_MAC_PHYREGADDR_MAXVAL >= regaddr);
1326 
1327     /* Check to see which MAC is actually in charge of PHY interface */
1328     if((struct mss_mac_instance *)0UL != this_mac_in->phy_controller)
1329     {
1330         this_mac = (const mss_mac_instance_t *)this_mac_in->phy_controller;
1331     }
1332     else
1333     {
1334         this_mac = this_mac_in;
1335     }
1336 
1337     /*
1338      * Write PHY address in MII Mgmt address register.
1339      * Makes previous register address 0 & invalid.
1340      *
1341      * Don't check mac_available flag here as we may be called in the MAC init
1342      * phase before everything else is in place...
1343      */
1344     if((MSS_MAC_PHYADDR_MAXVAL >= phyaddr) &&
1345        (MSS_MAC_PHYREGADDR_MAXVAL >= regaddr))
1346     {
1347         phy_op = GEM_WRITE1 | (GEM_PHY_OP_CL22_READ << GEM_OPERATION_SHIFT) | (((uint32_t)(2UL)) << GEM_WRITE10_SHIFT);
1348         phy_op |= ((uint32_t)phyaddr << GEM_PHY_ADDRESS_SHIFT) & GEM_PHY_ADDRESS;
1349         phy_op |= ((uint32_t)regaddr << GEM_REGISTER_ADDRESS_SHIFT) & GEM_REGISTER_ADDRESS;
1350 
1351         /*
1352          * Always use the pMAC for this as the eMAC MDIO interface is not
1353          * connected to the outside world...
1354          */
1355         lev = HAL_disable_interrupts();
1356         /* Wait for MII Mgmt interface to complete previous operation. */
1357         do
1358         {
1359             volatile int32_t ix;
1360             ix++;
1361         } while(0U == (this_mac->mac_base->NETWORK_STATUS & GEM_MAN_DONE));
1362 
1363         this_mac->mac_base->PHY_MANAGEMENT = phy_op;
1364 
1365         do
1366         {
1367             volatile int32_t ix;
1368             ix++;
1369         } while(0U == (this_mac->mac_base->NETWORK_STATUS & GEM_MAN_DONE));
1370 
1371         phy_op = this_mac->mac_base->PHY_MANAGEMENT;
1372         HAL_restore_interrupts(lev);
1373     }
1374     else
1375     {
1376         phy_op = 0U;
1377     }
1378 
1379     return((uint16_t)phy_op);
1380 }
1381 
1382 
1383 /******************************************************************************
1384  * See mss_ethernet_mac.h for details of how to use this function.
1385  */
1386 void
MSS_MAC_phy_reset(const mss_mac_instance_t * this_mac,mss_mac_phy_reset_t reset_type,bool reset_state)1387 MSS_MAC_phy_reset
1388 (
1389     const mss_mac_instance_t *this_mac,
1390     mss_mac_phy_reset_t reset_type,
1391     bool     reset_state
1392 )
1393 {
1394 #if defined(MSS_MAC_PHY_HW_RESET) || defined(MSS_MAC_PHY_HW_SRESET)
1395     /* Reset pointer to base MAC structure */
1396     if(&g_emac0 == this_mac)
1397     {
1398         this_mac = &g_mac0;
1399     }
1400 
1401     if(&g_emac1 == this_mac)
1402     {
1403         this_mac = &g_mac1;
1404     }
1405 
1406     if(MSS_MAC_SOFT_RESET == reset_type)
1407     {
1408         if((GPIO_TypeDef *)0UL != this_mac->phy_soft_reset_gpio)
1409         {
1410             MSS_GPIO_set_output(this_mac->phy_soft_reset_gpio, this_mac->phy_soft_reset_pin, reset_state);
1411         }
1412     }
1413     else
1414     {
1415         if((GPIO_TypeDef *)0UL != this_mac->phy_hard_reset_gpio)
1416         {
1417             MSS_GPIO_set_output(this_mac->phy_hard_reset_gpio, this_mac->phy_hard_reset_pin, reset_state);
1418         }
1419     }
1420 #else
1421     (void)this_mac;
1422     (void)reset_type;
1423     (void)reset_state;
1424 #endif
1425 }
1426 
1427 
1428 /******************************************************************************
1429  * See mss_ethernet_mac.h for details of how to use this function.
1430  */
1431 
1432 /* Divide by 4 as offset is in bytes but pointer is 4 bytes */
1433 #define GEM_REG_OFFSET(x) (offsetof(MAC_TypeDef, x) / 4)
1434 
1435 uint32_t
MSS_MAC_read_stat(const mss_mac_instance_t * this_mac,mss_mac_stat_t stat)1436 MSS_MAC_read_stat
1437 (
1438     const mss_mac_instance_t *this_mac,
1439     mss_mac_stat_t stat
1440 )
1441 {
1442     uint32_t stat_val = 0u;
1443 
1444     static uint64_t const stat_regs_lut[] =
1445     {
1446         GEM_REG_OFFSET(OCTETS_TXED_BOTTOM),
1447         GEM_REG_OFFSET(OCTETS_TXED_TOP),
1448         GEM_REG_OFFSET(FRAMES_TXED_OK),
1449         GEM_REG_OFFSET(BROADCAST_TXED),
1450         GEM_REG_OFFSET(MULTICAST_TXED),
1451         GEM_REG_OFFSET(PAUSE_FRAMES_TXED),
1452         GEM_REG_OFFSET(FRAMES_TXED_64),
1453         GEM_REG_OFFSET(FRAMES_TXED_65),
1454         GEM_REG_OFFSET(FRAMES_TXED_128),
1455         GEM_REG_OFFSET(FRAMES_TXED_256),
1456         GEM_REG_OFFSET(FRAMES_TXED_512),
1457         GEM_REG_OFFSET(FRAMES_TXED_1024),
1458         GEM_REG_OFFSET(FRAMES_TXED_1519),
1459         GEM_REG_OFFSET(TX_UNDERRUNS),
1460         GEM_REG_OFFSET(SINGLE_COLLISIONS),
1461         GEM_REG_OFFSET(MULTIPLE_COLLISIONS),
1462         GEM_REG_OFFSET(EXCESSIVE_COLLISIONS),
1463         GEM_REG_OFFSET(LATE_COLLISIONS),
1464         GEM_REG_OFFSET(DEFERRED_FRAMES),
1465         GEM_REG_OFFSET(CRS_ERRORS),
1466         GEM_REG_OFFSET(OCTETS_RXED_BOTTOM),
1467         GEM_REG_OFFSET(OCTETS_RXED_TOP),
1468         GEM_REG_OFFSET(FRAMES_RXED_OK),
1469         GEM_REG_OFFSET(BROADCAST_RXED),
1470         GEM_REG_OFFSET(MULTICAST_RXED),
1471         GEM_REG_OFFSET(PAUSE_FRAMES_RXED),
1472         GEM_REG_OFFSET(FRAMES_RXED_64),
1473         GEM_REG_OFFSET(FRAMES_RXED_65),
1474         GEM_REG_OFFSET(FRAMES_RXED_128),
1475         GEM_REG_OFFSET(FRAMES_RXED_256),
1476         GEM_REG_OFFSET(FRAMES_RXED_512),
1477         GEM_REG_OFFSET(FRAMES_RXED_1024),
1478         GEM_REG_OFFSET(FRAMES_RXED_1519),
1479         GEM_REG_OFFSET(UNDERSIZE_FRAMES),
1480         GEM_REG_OFFSET(EXCESSIVE_RX_LENGTH),
1481         GEM_REG_OFFSET(RX_JABBERS),
1482         GEM_REG_OFFSET(FCS_ERRORS),
1483         GEM_REG_OFFSET(RX_LENGTH_ERRORS),
1484         GEM_REG_OFFSET(RX_SYMBOL_ERRORS),
1485         GEM_REG_OFFSET(ALIGNMENT_ERRORS),
1486         GEM_REG_OFFSET(RX_RESOURCE_ERRORS),
1487         GEM_REG_OFFSET(RX_OVERRUNS),
1488         GEM_REG_OFFSET(RX_IP_CK_ERRORS),
1489         GEM_REG_OFFSET(RX_TCP_CK_ERRORS),
1490         GEM_REG_OFFSET(RX_UDP_CK_ERRORS),
1491         GEM_REG_OFFSET(AUTO_FLUSHED_PKTS)
1492     };
1493 
1494     ASSERT(MSS_MAC_LAST_STAT > stat);
1495 
1496     if((MSS_MAC_LAST_STAT > stat) && (MSS_MAC_AVAILABLE == this_mac->mac_available))
1497     {
1498         if(0U != this_mac->is_emac)
1499         {
1500             stat_val = *(((uint32_t *)this_mac->emac_base) + stat_regs_lut[stat]);
1501         }
1502         else
1503         {
1504             stat_val = *(((uint32_t *)this_mac->mac_base) + stat_regs_lut[stat]);
1505         }
1506     }
1507 
1508     return stat_val;
1509 }
1510 
1511 
1512 /*******************************************************************************
1513  See mss_ethernet_mac.h for details of how to use this function
1514 */
MSS_MAC_clear_statistics(const mss_mac_instance_t * this_mac)1515 void MSS_MAC_clear_statistics
1516 (
1517     const mss_mac_instance_t *this_mac
1518 )
1519 {
1520     if((0U != this_mac->is_emac) && (MSS_MAC_AVAILABLE == this_mac->mac_available))
1521     {
1522         this_mac->emac_base->NETWORK_CONTROL |= GEM_CLEAR_ALL_STATS_REGS;
1523     }
1524     else
1525     {
1526         this_mac->mac_base->NETWORK_CONTROL |= GEM_CLEAR_ALL_STATS_REGS;
1527     }
1528 }
1529 
1530 
1531 /******************************************************************************
1532  * See mss_ethernet_mac.h for details of how to use this function.
1533  */
1534 uint8_t
MSS_MAC_receive_pkt(mss_mac_instance_t * this_mac,uint32_t queue_no,uint8_t * rx_pkt_buffer,void * p_user_data,mss_mac_rx_int_ctrl_t enable)1535 MSS_MAC_receive_pkt
1536 (
1537     mss_mac_instance_t *this_mac,
1538     uint32_t queue_no,
1539     uint8_t * rx_pkt_buffer,
1540     void * p_user_data,
1541     mss_mac_rx_int_ctrl_t enable
1542 )
1543 {
1544     uint8_t status = MSS_MAC_FAILED;
1545     /* Make this function atomic w.r.to EMAC interrupt */
1546 
1547     /* PLIC_DisableIRQ() et al should not be called from the associated interrupt... */
1548     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
1549     {
1550         if(0U == this_mac->queue[queue_no].in_isr)
1551         {
1552             if(0U != this_mac->use_local_ints)
1553             {
1554                 __disable_local_irq(this_mac->mac_q_int[queue_no]);
1555             }
1556             else
1557             {
1558                 PLIC_DisableIRQ(this_mac->mac_q_int[queue_no]); /* Single interrupt from GEM? */
1559             }
1560         }
1561 
1562         ASSERT(NULL_POINTER != rx_pkt_buffer);
1563         ASSERT(IS_WORD_ALIGNED(rx_pkt_buffer));
1564 
1565         if(this_mac->queue[queue_no].nb_available_rx_desc > 0U)
1566         {
1567             uint32_t next_rx_desc_index;
1568 
1569             if(MSS_MAC_INT_DISABLE == enable)
1570             {
1571                 /*
1572                  * When setting up the chain of buffers, we don't want the DMA
1573                  * engine active so shut down reception.
1574                  */
1575                 if(0U != this_mac->is_emac)
1576                 {
1577                     this_mac->emac_base->NETWORK_CONTROL &= ~GEM_ENABLE_RECEIVE;
1578                 }
1579                 else
1580                 {
1581                     this_mac->mac_base->NETWORK_CONTROL &= ~GEM_ENABLE_RECEIVE;
1582                 }
1583             }
1584 
1585             --this_mac->queue[queue_no].nb_available_rx_desc;
1586             next_rx_desc_index = this_mac->queue[queue_no].next_free_rx_desc_index;
1587 
1588             if((MSS_MAC_RX_RING_SIZE - 1U) == next_rx_desc_index)
1589             {
1590                 this_mac->queue[queue_no].rx_desc_tab[next_rx_desc_index].addr_low = (uint32_t)((uint64_t)rx_pkt_buffer | 2UL);  /* Set wrap bit */
1591             }
1592             else
1593             {
1594                 this_mac->queue[queue_no].rx_desc_tab[next_rx_desc_index].addr_low = (uint32_t)((uint64_t)rx_pkt_buffer);
1595             }
1596 
1597 #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
1598             this_mac->queue[queue_no].rx_desc_tab[next_rx_desc_index].addr_high = (uint32_t)((uint64_t)rx_pkt_buffer >> 32);
1599 #endif
1600             this_mac->queue[queue_no].rx_caller_info[next_rx_desc_index] = p_user_data;
1601 
1602             /*
1603                If the RX is found disabled, then it might be because this is the
1604                first time a packet is scheduled for reception or the RX ENABLE is
1605                made zero by RX overflow or RX bus error. In either case, this
1606                function tries to schedule the current packet for reception.
1607 
1608                Don't bother if we are not enabling interrupt at the end of all this...
1609             */
1610             if(MSS_MAC_INT_ARM == enable)
1611             {
1612                 /*
1613                  * Starting receive operations off with a chain of buffers set up.
1614                  */
1615 
1616                 if(0U != this_mac->is_emac)
1617                 {
1618                     this_mac->emac_base->NETWORK_CONTROL &= ~GEM_ENABLE_RECEIVE;
1619                     this_mac->emac_base->RECEIVE_Q_PTR = (uint32_t)((uint64_t)this_mac->queue[queue_no].rx_desc_tab);
1620 #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
1621                     this_mac->emac_base->UPPER_RX_Q_BASE_ADDR = (uint32_t)((uint64_t)this_mac->queue[queue_no].rx_desc_tab >> 32);
1622 #endif
1623                     this_mac->emac_base->NETWORK_CONTROL |= GEM_ENABLE_RECEIVE;
1624                 }
1625                 else
1626                 {
1627                     this_mac->mac_base->NETWORK_CONTROL &= ~GEM_ENABLE_RECEIVE;
1628                     *(this_mac->queue[queue_no].receive_q_ptr) = (uint32_t)((uint64_t)this_mac->queue[queue_no].rx_desc_tab);
1629 #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
1630                     this_mac->mac_base->UPPER_RX_Q_BASE_ADDR = (uint32_t)((uint64_t)this_mac->queue[queue_no].rx_desc_tab >> 32);
1631 #endif
1632                     this_mac->mac_base->NETWORK_CONTROL |= GEM_ENABLE_RECEIVE;
1633                 }
1634             }
1635             else
1636             {
1637                 if(MSS_MAC_INT_DISABLE != enable)
1638                 {
1639                     uint32_t temp_cr;
1640 
1641                     if(0U != this_mac->is_emac)
1642                     {
1643                         temp_cr = this_mac->emac_base->NETWORK_CONTROL;
1644                     }
1645                     else
1646                     {
1647                         temp_cr = this_mac->mac_base->NETWORK_CONTROL;
1648                     }
1649                     if(0U == (temp_cr & GEM_ENABLE_RECEIVE))
1650                     {
1651                         /* RX disabled so restart it... */
1652                         if(0U != this_mac->is_emac)
1653                         {
1654                             this_mac->emac_base->NETWORK_CONTROL |= GEM_ENABLE_RECEIVE;
1655                         }
1656                         else
1657                         {
1658                             this_mac->mac_base->NETWORK_CONTROL |= GEM_ENABLE_RECEIVE;
1659                         }
1660                     }
1661                 }
1662             }
1663 
1664             /* Point the next_rx_desc to next free descriptor in the ring */
1665             /* Wrap around in case next descriptor is pointing to last in the ring */
1666             ++this_mac->queue[queue_no].next_free_rx_desc_index;
1667             this_mac->queue[queue_no].next_free_rx_desc_index %= MSS_MAC_RX_RING_SIZE;
1668 
1669         }
1670 
1671         /*
1672          * Only call Ethernet Interrupt Enable function if the user says so.
1673          * See note above for disable...
1674          */
1675         if((MSS_MAC_INT_ARM == enable) && (0U == this_mac->queue[queue_no].in_isr))
1676         {
1677             if(0U != this_mac->use_local_ints)
1678             {
1679                 __enable_local_irq(this_mac->mac_q_int[queue_no]);
1680             }
1681             else
1682             {
1683                 PLIC_EnableIRQ(this_mac->mac_q_int[queue_no]); /* Single interrupt from GEM? */
1684             }
1685         }
1686     }
1687 
1688     return status;
1689 }
1690 
1691 #if defined(MSS_MAC_UNH_TEST)
1692 /******************************************************************************
1693  * We take a lot of short cuts here as we "know" we are called from ISR and
1694  * are only supposed to be called for pMAC queue 0, we assume the packet buffer
1695  * for this descriptor has not changed,  we ignore caller_info etc...
1696  */
1697 void
MSS_MAC_receive_pkt_isr(mss_mac_instance_t * this_mac)1698 MSS_MAC_receive_pkt_isr
1699 (
1700     mss_mac_instance_t *this_mac
1701 )
1702 {
1703     mss_mac_queue_t *p_queue = &this_mac->queue[0];
1704 
1705     --p_queue->nb_available_rx_desc;
1706 
1707     /* clear used bit and time stamp present bit */
1708     p_queue->rx_desc_tab[p_queue->next_free_rx_desc_index].addr_low &= 0xFFFFFFFA;
1709 
1710     /* Point the next_rx_desc to next free descriptor in the ring */
1711     /* Wrap around in case next descriptor is pointing to last in the ring */
1712     ++p_queue->next_free_rx_desc_index;
1713     p_queue->next_free_rx_desc_index %= MSS_MAC_RX_RING_SIZE;
1714 }
1715 #endif
1716 
1717 /*******************************************************************************
1718  * See mss_ethernet_mac.h for details of how to use this function.
1719  */
1720 int32_t
MSS_MAC_send_pkt(mss_mac_instance_t * this_mac,uint32_t queue_no,uint8_t const * tx_buffer,uint32_t length,void * p_user_data)1721 MSS_MAC_send_pkt
1722 (
1723     mss_mac_instance_t *this_mac,
1724     uint32_t queue_no,
1725     uint8_t const * tx_buffer,
1726     uint32_t length,
1727     void * p_user_data
1728 )
1729 {
1730     /*
1731      * Simplified transmit operation which depends on the following assumptions:
1732      *
1733      * 1. The TX DMA buffer size is big enough to contain a full packet.
1734      * 2. We will only transmit one packet at a time.
1735      * 3. We wait for any outstanding transmits on other queues to complete
1736      *    because we need to ALWAYS write to the queue 0 pointer to trigger
1737      *    internal restart of the DMA process.
1738      *
1739      * We do transmission by using two buffer descriptors. The first contains the
1740      * packet to transmit and the second is a dummy one with the USED bit set. This
1741      * halts transmission once the first packet is transmitted. We always reset the
1742      * TX DMA to point to the first packet when we send a packet so we don't have
1743      * to juggle buffer positions or worry about wrap.
1744      */
1745     uint32_t tx_length = length;
1746     int32_t status = MSS_MAC_ERR_NOT_DONE;
1747     /*
1748      *  Hack for system testing. If b31 of the tx_length is 1 then we want to
1749      * send without a CRC appended. This is used for loopback testing where we
1750      * can get the GEM to receive packets with CRC appended and send them
1751      * straight back.
1752      */
1753     int32_t no_crc = 0;
1754     volatile int delay;
1755     volatile uint32_t *p_nw_control;
1756     volatile uint32_t *p_tx_status;
1757 
1758     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
1759     {
1760         /* Is config option for disabling CRC set? */
1761         if(MSS_MAC_CRC_DISABLE == this_mac->append_CRC)
1762         {
1763             no_crc = 1;
1764         }
1765 
1766         /* Or has the user requested just this packet? */
1767         if(0U != (tx_length & 0x80000000U))
1768         {
1769             no_crc = 1;
1770         }
1771 
1772         tx_length &= 0x7FFFFFFFU; /* Make sure high bit is now clear */
1773 
1774         /* Make this function atomic w.r.to EMAC interrupt */
1775         /* PLIC_DisableIRQ() et al should not be called from the associated interrupt... */
1776         if(0U == this_mac->queue[queue_no].in_isr)
1777         {
1778             if(0U != this_mac->use_local_ints)
1779             {
1780                 __disable_local_irq(this_mac->mac_q_int[queue_no]);
1781             }
1782             else
1783             {
1784                 PLIC_DisableIRQ(this_mac->mac_q_int[queue_no]); /* Single interrupt from GEM? */
1785             }
1786         }
1787 
1788         ASSERT(NULL_POINTER != tx_buffer);
1789         ASSERT(0U != tx_length);
1790         ASSERT(IS_WORD_ALIGNED(tx_buffer));
1791 
1792         /* We use these a lot and this cuts down on conditional code later on */
1793         if(0U != this_mac->is_emac)
1794         {
1795             p_nw_control = &this_mac->emac_base->NETWORK_CONTROL;
1796             p_tx_status  = &this_mac->emac_base->TRANSMIT_STATUS;
1797         }
1798         else
1799         {
1800             p_nw_control = &this_mac->mac_base->NETWORK_CONTROL;
1801             p_tx_status  = &this_mac->mac_base->TRANSMIT_STATUS;
1802         }
1803 
1804 #if defined(MSS_MAC_SIMPLE_TX_QUEUE)
1805         if(this_mac->queue[queue_no].nb_available_tx_desc == (uint32_t)MSS_MAC_TX_RING_SIZE)
1806         {
1807             /* Queue is fully available for transmit so clear retry count */
1808             this_mac->queue[queue_no].tries = 0UL;
1809 
1810             /* Make sure transmit is enabled */
1811             if(0 == (*p_nw_control & GEM_ENABLE_TRANSMIT))
1812                 {
1813                 *p_nw_control = *p_nw_control | GEM_ENABLE_TRANSMIT;
1814                 }
1815             /*
1816              * Wait for pending transmits to complete as you cannot alter
1817              * tx queue pointers while transmit is active...
1818              */
1819             while(0 != (*p_tx_status & GEM_TRANSMIT_GO))
1820             {
1821                 delay++; /* Empty loop will cause debug issues... */
1822             }
1823 
1824             /* Make sure queue is currently disabled */
1825             *this_mac->queue[queue_no].transmit_q_ptr = (uint32_t)((uint64_t)this_mac->queue[queue_no].tx_desc_tab) | 1UL;
1826 
1827             /* Set up tx descriptor for this packet */
1828             this_mac->queue[queue_no].nb_available_tx_desc--;
1829             this_mac->queue[queue_no].current_tx_desc = 0;
1830             this_mac->queue[queue_no].tx_desc_tab[0].addr_low = (uint32_t)((uint64_t)tx_buffer);
1831 
1832             /* Mark as last buffer for frame */
1833             this_mac->queue[queue_no].tx_desc_tab[0].status   = (tx_length & GEM_TX_DMA_BUFF_LEN) | GEM_TX_DMA_LAST;
1834             if(0 != no_crc)
1835             {
1836                 this_mac->queue[queue_no].tx_desc_tab[0].status |= GEM_TX_DMA_NO_CRC;
1837             }
1838 #if 0
1839             this_mac->tx_desc_tab[0].status = (tx_length & GEM_TX_DMA_BUFF_LEN) | GEM_TX_DMA_LAST | GEM_TX_DMA_USED; /* PMCS deliberate error ! */
1840 #endif
1841 #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
1842             this_mac->queue[queue_no].tx_desc_tab[0].addr_high = (uint32_t)((uint64_t)tx_buffer >> 32);
1843             this_mac->queue[queue_no].tx_desc_tab[0].unused    = 0U;
1844 #endif
1845 
1846             this_mac->queue[queue_no].tx_desc_tab[1].status   =  GEM_TX_DMA_WRAP | GEM_TX_DMA_LAST |  GEM_TX_DMA_USED ;
1847 
1848             this_mac->queue[queue_no].tx_caller_info[0] = p_user_data;
1849 
1850             *this_mac->queue[queue_no].transmit_q_ptr = (uint32_t)((uint64_t)&this_mac->queue[queue_no].tx_desc_tab[0]);
1851             /*
1852              * If not queue 0 then we need to write disabled value to queue 0 to
1853              * get the DMA engine reloaded...
1854              */
1855             if(0 != queue_no)
1856             {
1857                 *this_mac->queue[0].transmit_q_ptr = (uint32_t)((uint64_t)this_mac->queue[0].tx_desc_tab) | 1U;
1858             }
1859 
1860             /* When transmitting at 10M, this delay is needed, 625MHz cpu clock - YMMV */
1861             for(delay = 0; delay != 8; delay++)
1862             {
1863             }
1864 
1865             *p_nw_control = *p_nw_control | GEM_TRANSMIT_START;
1866 
1867             this_mac->queue[queue_no].egress += tx_length;
1868             status = MSS_MAC_ERR_OK;
1869         }
1870         else
1871         {
1872             /*
1873              * Queue not available so lets check some things...
1874              */
1875             if(0 == (*p_nw_control & GEM_ENABLE_TRANSMIT))
1876             {
1877                 /*
1878                  * TX is currently disabled so re-enable it and restart the last
1879                  * operation on this queue to see if that gets us a completion.
1880                  */
1881                 this_mac->queue[queue_no].tx_reenable++;
1882                 *p_nw_control = *p_nw_control | GEM_ENABLE_TRANSMIT;
1883                 *this_mac->queue[queue_no].transmit_q_ptr = (uint32_t)((uint64_t)&this_mac->queue[queue_no].tx_desc_tab[0]);
1884                 if(0 != queue_no)
1885                 {
1886                     *this_mac->queue[0].transmit_q_ptr = (uint32_t)((uint64_t)this_mac->queue[0].tx_desc_tab) | 1U;
1887                 }
1888 
1889                 /* When transmitting at 10M, this delay is needed, 625MHz cpu clock - YMMV */
1890                 for(delay = 0; delay != 8; delay++)
1891                 {
1892                 }
1893 
1894                 *p_nw_control = *p_nw_control | GEM_TRANSMIT_START;
1895             }
1896             else
1897             {
1898                 /* Kick the tx start bit in case we are stalled... */
1899                 this_mac->queue[queue_no].tx_restart++;
1900                 *p_nw_control = *p_nw_control | GEM_TRANSMIT_START;
1901             }
1902 
1903             /*
1904              * TX might have completed since we entered the function but if we
1905              * seem to be spinning on this and buffers haven't been returned to
1906              * the queue then just give up and reset queue.
1907              */
1908             if(this_mac->queue[queue_no].tx_desc_tab[0].status & GEM_TX_DMA_USED)
1909             {
1910                 this_mac->queue[queue_no].tries++;
1911 
1912                 if(this_mac->queue[queue_no].tries > 3) /* Been here too often? */
1913                 {
1914                     /* Give up and reset FW queue count */
1915                     this_mac->queue[queue_no].nb_available_tx_desc = (uint32_t)MSS_MAC_TX_RING_SIZE;
1916                     status = MSS_MAC_ERR_TX_TIMEOUT;
1917                 }
1918             }
1919 
1920             if(this_mac->queue[queue_no].tx_desc_tab[0].status & (GEM_TX_DMA_RETRY_ERROR | GEM_TX_DMA_UNDERRUN | GEM_TX_DMA_BUS_ERROR | GEM_TX_DMA_LATE_COL_ERROR | GEM_TX_DMA_OFFLOAD_ERRORS))
1921             {
1922                 /* Give up and reset FW queue count */
1923                 this_mac->queue[queue_no].nb_available_tx_desc = (uint32_t)MSS_MAC_TX_RING_SIZE;
1924                 status = MSS_MAC_ERR_TX_FAIL;
1925             }
1926         }
1927 #else
1928         /* TBD PMCS need to implement multi packet queuing... */
1929 #warning "Nothing implemented for multi packet tx yet"
1930 #endif
1931         /* Ethernet Interrupt Enable function. */
1932         /* PLIC_DisableIRQ() et al should not be called from the associated interrupt... */
1933         if(0U == this_mac->queue[queue_no].in_isr)
1934         {
1935             if(0U != this_mac->use_local_ints)
1936             {
1937                 __enable_local_irq(this_mac->mac_q_int[queue_no]);
1938             }
1939             else
1940             {
1941                 PLIC_EnableIRQ(this_mac->mac_q_int[queue_no]); /* Single interrupt from GEM? */
1942             }
1943         }
1944     }
1945     return status;
1946 }
1947 
1948 
1949 /*******************************************************************************
1950  * See mss_ethernet_mac.h for details of how to use this function.
1951  */
1952 int32_t
MSS_MAC_send_pkts(mss_mac_instance_t * this_mac,uint32_t queue_mask,mss_mac_tx_pkt_info_t * p_packets)1953 MSS_MAC_send_pkts
1954 (
1955     mss_mac_instance_t    *this_mac,
1956     uint32_t               queue_mask,
1957     mss_mac_tx_pkt_info_t *p_packets
1958 )
1959 {
1960     /*
1961      * Multi packet, multi queue transmit operation which depends on the
1962      * following assumptions:
1963      *
1964      * 1. queue_mask indicates the queues which may be involved so that we can
1965      *    properly handle ISR vs normal calling.
1966      *    Set the mask to 0x0000000F to indicate all queues if there is any
1967      *    uncertainty.
1968      *    Set the mask to 0xFFFFFFF0 to indicate we are being called from a GEM
1969      *    ISR.
1970      * 2. We wait for any outstanding transmits on other queues to complete
1971      *    because we need to ALWAYS write to the queue 0 pointer to trigger
1972      *    internal restart of the DMA process.
1973      * 3. We accept at most MSS_MAC_TX_RING_SIZE-1 packets as the final packet
1974      *    in the chain is a dummy one to get the TX DMA engine to stop. Any
1975      *    packets beyond that are silently dropped.
1976      *
1977      * We do transmission by using multiple buffer descriptors. The initial
1978      * descriptors are for the packet(s) to transmit and the last is a dummy one
1979      * with the USED bit set. This halts transmission once the first packet is
1980      * transmitted. We always reset the TX DMA to point to the first packet when
1981      * we send packets so we don't have to juggle buffer positions or worry
1982      * about wrap.
1983      */
1984     uint32_t mask_bit;
1985     uint32_t counter;
1986     int32_t  status = MSS_MAC_ERR_NOT_DONE;
1987     bool tx_done;
1988     uint32_t queues;
1989     mss_mac_tx_pkt_info_t *tx_rover;
1990     /*
1991      */
1992     int32_t no_crc = 0;
1993     volatile int delay;
1994     volatile uint32_t *p_nw_control;
1995     volatile uint32_t *p_tx_status;
1996 
1997     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
1998     {
1999         /* We use these a lot and this cuts down on conditional code later on */
2000         if(0U != this_mac->is_emac)
2001         {
2002             p_nw_control = &this_mac->emac_base->NETWORK_CONTROL;
2003             p_tx_status  = &this_mac->emac_base->TRANSMIT_STATUS;
2004             queues = 1;
2005         }
2006         else
2007         {
2008             p_nw_control = &this_mac->mac_base->NETWORK_CONTROL;
2009             p_tx_status  = &this_mac->mac_base->TRANSMIT_STATUS;
2010             queues = 4;
2011         }
2012 
2013         /* PLIC_DisableIRQ() et al should not be called from the associated interrupt... */
2014         if(0xFFFFFFF0U != queue_mask) /* Not called from ISR */
2015         {
2016             /*
2017              * Make this function atomic w.r.to EMAC interrupt for the queues we
2018              * are using and queue 0.
2019              */
2020             mask_bit = 1;
2021             queue_mask |= 1U; /* Force queue 0 interrupt disable */
2022             for(counter = 0; counter != 4; counter++)
2023             {
2024                 if(0 != (mask_bit & queue_mask))
2025                 {
2026                     if(0U != this_mac->use_local_ints)
2027                     {
2028                         __disable_local_irq(this_mac->mac_q_int[counter]);
2029                     }
2030                     else
2031                     {
2032                         PLIC_DisableIRQ(this_mac->mac_q_int[counter]); /* Single interrupt from GEM? */
2033                     }
2034                 }
2035 
2036                 mask_bit <<= 1;
2037             }
2038         }
2039 
2040         tx_done = true;
2041         for(counter = 0; counter != queues; counter++)
2042         {
2043             if(this_mac->queue[counter].nb_available_tx_desc != (uint32_t)MSS_MAC_TX_RING_SIZE)
2044             {
2045                 tx_done = false; /* Not done if any queue still active */
2046             }
2047         }
2048 
2049         if(tx_done)
2050         {
2051             /* Queues are fully available for transmit so clear retry counts */
2052             for(counter = 0; counter != queues; counter++)
2053             {
2054                 /* Make sure queue is currently disabled */
2055                 *this_mac->queue[counter].transmit_q_ptr = (uint32_t)((uint64_t)this_mac->queue[counter].tx_desc_tab) | 1UL;
2056                 this_mac->queue[counter].tries = 0UL;
2057             }
2058 
2059 
2060             /* Make sure transmit is enabled */
2061             if(0 == (*p_nw_control & GEM_ENABLE_TRANSMIT))
2062                 {
2063                 *p_nw_control = *p_nw_control | GEM_ENABLE_TRANSMIT;
2064                 }
2065             /*
2066              * Wait for pending transmits to complete as you cannot alter
2067              * tx queue pointers while transmit is active...
2068              */
2069             while(0 != (*p_tx_status & GEM_TRANSMIT_GO))
2070             {
2071                 delay++; /* Empty loop will cause debug issues... */
2072             }
2073 
2074             /* All is quiet now so let's construct the TX queue(s) */
2075 
2076             tx_rover = p_packets;
2077             while(0 != tx_rover->length)
2078             {
2079                 uint32_t tx_length;
2080                 mss_mac_queue_t *p_queue;
2081 
2082                 tx_length = tx_rover->length;
2083 
2084                 /* Is config option for disabling CRC set? */
2085                 if(MSS_MAC_CRC_DISABLE == this_mac->append_CRC)
2086                 {
2087                     no_crc = 1;
2088                 }
2089 
2090                 /* Or has the user requested just this packet? */
2091                 if(0U != (tx_length & 0x80000000U))
2092                 {
2093                     no_crc = 1;
2094                     tx_length &= 0x7FFFFFFFU; /* Make sure high bit is now clear */
2095                 }
2096 
2097 
2098                 /*
2099                  * We need to leave one spare at the end to halt the DMA when we
2100                  * are done...
2101                  */
2102                 p_queue  = &this_mac->queue[tx_rover->queue_no];
2103                 if(p_queue->nb_available_tx_desc > 1)
2104                 {
2105                     uint32_t position;
2106                     mss_mac_tx_desc_t *p_desc;
2107 
2108 
2109                     /* Set up tx descriptor for this packet */
2110                     position = MSS_MAC_TX_RING_SIZE - p_queue->nb_available_tx_desc;
2111                     p_desc   = &p_queue->tx_desc_tab[position];
2112 
2113                     p_queue->nb_available_tx_desc--;
2114                     p_queue->current_tx_desc = 0;
2115                     p_desc->addr_low = (uint32_t)((uint64_t)tx_rover->tx_buffer);
2116 
2117                     /* Mark as last buffer for frame */
2118                     p_desc->status = (tx_length & GEM_TX_DMA_BUFF_LEN) | GEM_TX_DMA_LAST;
2119                     if(0 != no_crc)
2120                     {
2121                         p_desc->status |= GEM_TX_DMA_NO_CRC;
2122                     }
2123 #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
2124                     p_desc->addr_high = (uint32_t)((uint64_t)tx_rover->tx_buffer >> 32);
2125                     p_desc->unused    = 0U;
2126 #endif
2127 
2128                     (p_desc + 1)->status |= GEM_TX_DMA_WRAP | GEM_TX_DMA_USED;
2129                     p_queue->tx_caller_info[position] = tx_rover->p_user_data;
2130 
2131                     p_queue->egress += tx_length;
2132                 }
2133 
2134                 tx_rover++;
2135             }
2136 
2137             counter = queues;
2138             while(0 != counter)
2139             {
2140                 counter--;
2141                 if(this_mac->queue[counter].nb_available_tx_desc != (uint32_t)MSS_MAC_TX_RING_SIZE)
2142                 {
2143                     *this_mac->queue[counter].transmit_q_ptr = (uint32_t)((uint64_t)&this_mac->queue[counter].tx_desc_tab[0]);
2144                 }
2145             }
2146 
2147             /* If queue 0 not used we still need a dummy write... */
2148             if(this_mac->queue[0].nb_available_tx_desc == (uint32_t)MSS_MAC_TX_RING_SIZE)
2149             {
2150                 *this_mac->queue[0].transmit_q_ptr = (uint32_t)((uint64_t)this_mac->queue[0].tx_desc_tab) | 1U;
2151             }
2152 
2153             /* When transmitting at 10M, this delay is needed, 625MHz cpu clock - YMMV */
2154             for(delay = 0; delay != 8; delay++)
2155             {
2156             }
2157 
2158             *p_nw_control = *p_nw_control | GEM_TRANSMIT_START;
2159 
2160             status = MSS_MAC_ERR_OK;
2161         }
2162         else /* tx_done */
2163         {
2164             /*
2165              * Queues not available so lets check some things...
2166              */
2167             if(0 == (*p_nw_control & GEM_ENABLE_TRANSMIT))
2168             {
2169                 /*
2170                  * TX is currently disabled so re-enable it and restart the last
2171                  * operation on the queues to see if that gets us a completion.
2172                  */
2173                 counter = queues;
2174                 while(0 != counter)
2175                 {
2176                     counter--;
2177                     if(this_mac->queue[counter].nb_available_tx_desc != (uint32_t)MSS_MAC_TX_RING_SIZE)
2178                     {
2179                         bool test_done = false;
2180                         mss_mac_tx_desc_t *p_descriptor;
2181 
2182                         /* Scan descriptor lists to see where they are at */
2183                         p_descriptor = &this_mac->queue[counter].tx_desc_tab[0];
2184                         while(!test_done)
2185                         {
2186                             if((p_descriptor->status & GEM_TX_DMA_USED) && (p_descriptor->status & GEM_TX_DMA_WRAP))
2187                             {
2188                                 /*
2189                                  * End of chain and no unsent packets...
2190                                  * Mark as all sent and disable queue.
2191                                  */
2192                                 *this_mac->queue[counter].transmit_q_ptr = (uint32_t)((uint64_t)this_mac->queue[counter].tx_desc_tab) | 1U;
2193                                 this_mac->queue[counter].nb_available_tx_desc = (uint32_t)MSS_MAC_TX_RING_SIZE;
2194                                 test_done = true;
2195                             }
2196                             else if(p_descriptor->status & GEM_TX_DMA_USED)
2197                             {
2198                                 /* Used but not last so try next one */
2199                                 p_descriptor++;
2200                             }
2201                             else /* Not used - restart from here */
2202                             {
2203                                 this_mac->queue[counter].tx_reenable++;
2204                                 *this_mac->queue[counter].transmit_q_ptr = (uint32_t)((uint64_t)p_descriptor);
2205                                 test_done = true;
2206                             }
2207                         }
2208                     }
2209                 }
2210 
2211                 *p_nw_control = *p_nw_control | GEM_ENABLE_TRANSMIT;
2212                 /* When transmitting at 10M, this delay is needed, 625MHz cpu clock - YMMV */
2213                 for(delay = 0; delay != 8; delay++)
2214                 {
2215                 }
2216 
2217                 *p_nw_control = *p_nw_control | GEM_TRANSMIT_START;
2218             }
2219             else
2220             {
2221                 /* Kick the tx start bit in case we are stalled... */
2222                 this_mac->queue[0].tx_restart++;
2223                 *p_nw_control = *p_nw_control | GEM_TRANSMIT_START;
2224             }
2225 
2226             /*
2227              * TX might have completed since we entered the function but if we
2228              * seem to be spinning on this and buffers haven't been returned to
2229              * the queue then just give up and reset queue.
2230              */
2231             for(counter = 0; counter != queues; counter++)
2232             {
2233                 bool test_done = false;
2234                 bool all_sent = false;
2235                 mss_mac_tx_desc_t *p_descriptor;
2236 
2237                 /* Scan descriptor lists to see where they are at */
2238                 p_descriptor = &this_mac->queue[counter].tx_desc_tab[0];
2239                 while(!test_done)
2240                 {
2241                     if((p_descriptor->status & GEM_TX_DMA_USED) && (p_descriptor->status & GEM_TX_DMA_WRAP))
2242                     {
2243                         /*
2244                          * End of chain and no unsent packets...
2245                          * Mark as all sent and disable queue.
2246                          */
2247                         all_sent  = true;
2248                         test_done = true;
2249                     }
2250                     else if(p_descriptor->status & GEM_TX_DMA_USED)
2251                     {
2252                         /* Used but not last so try next one */
2253                         p_descriptor++;
2254                     }
2255                     else /* Not used - not all sent yet */
2256                     {
2257                         test_done = true;
2258                     }
2259                 }
2260 
2261                 if(true == all_sent)
2262                 {
2263                     this_mac->queue[counter].tries++;
2264 
2265                     if(this_mac->queue[counter].tries > 3) /* Been here too often? */
2266                     {
2267                         /* Give up and reset FW queue count */
2268                         this_mac->queue[counter].nb_available_tx_desc = (uint32_t)MSS_MAC_TX_RING_SIZE;
2269                         status = MSS_MAC_ERR_TX_TIMEOUT;
2270                     }
2271                 }
2272             }
2273 
2274             for(counter = 0; counter != queues; counter++) /* Scan for TX fails */
2275             {
2276                 bool test_done = false;
2277                 mss_mac_tx_desc_t *p_descriptor;
2278 
2279                 /* Scan descriptor lists to see where they are at */
2280                 p_descriptor = &this_mac->queue[counter].tx_desc_tab[0];
2281                 while(!test_done)
2282                 {
2283                     if(p_descriptor->status & (GEM_TX_DMA_RETRY_ERROR | GEM_TX_DMA_UNDERRUN | GEM_TX_DMA_BUS_ERROR | GEM_TX_DMA_LATE_COL_ERROR | GEM_TX_DMA_OFFLOAD_ERRORS))
2284                     {
2285                         /* Give up and reset FW queue count on first fail */
2286                         this_mac->queue[counter].nb_available_tx_desc = (uint32_t)MSS_MAC_TX_RING_SIZE;
2287                         status = MSS_MAC_ERR_TX_FAIL;
2288                         test_done = true;
2289                     }
2290 
2291                     if(p_descriptor->status & GEM_TX_DMA_WRAP)
2292                     {
2293                         /* End of chain so bail */
2294                         test_done = true;
2295                     }
2296 
2297                     p_descriptor++;
2298                 }
2299             }
2300         }
2301 
2302         /* Ethernet Interrupt Enable function. */
2303         /* PLIC_DisableIRQ() et al should not be called from the associated interrupt... */
2304         if(0xFFFFFFF0U != queue_mask) /* Not called from ISR */
2305         {
2306             mask_bit = 1;
2307             for(counter = 0; counter != 4; counter++)
2308             {
2309                 if(0 != (mask_bit & queue_mask))
2310                 {
2311                     if(0U != this_mac->use_local_ints)
2312                     {
2313                         __enable_local_irq(this_mac->mac_q_int[counter]);
2314                     }
2315                     else
2316                     {
2317                         PLIC_EnableIRQ(this_mac->mac_q_int[counter]); /* Single interrupt from GEM? */
2318                     }
2319                 }
2320 
2321                 mask_bit <<= 1;
2322             }
2323         }
2324     }
2325     return status;
2326 }
2327 
2328 #if defined(MSS_MAC_SPEED_TEST)
2329 /* Very stripped down queue 0 packet blaster - assumes full tx queue0 is being
2330  * used on pMAC and does little or no checking. Don't call from GEM interrupts!
2331  * Don't use with local interrupts or eMAC either...
2332  */
2333 
copy8b(uint64_t * dest,uint64_t * source,uint32_t count)2334 void copy8b(uint64_t *dest, uint64_t *source, uint32_t count)
2335 {
2336     while(count--)
2337         *dest++ = *source++;
2338 }
2339 
2340 int32_t
MSS_MAC_send_pkts_fast(mss_mac_instance_t * this_mac,mss_mac_tx_desc_t * descriptors,uint32_t tx_count)2341 MSS_MAC_send_pkts_fast
2342 (
2343     mss_mac_instance_t    *this_mac,
2344     mss_mac_tx_desc_t *descriptors,
2345     uint32_t tx_count
2346 )
2347 {
2348     /*
2349      * Multi packet, multi queue transmit operation which depends on the
2350      * following assumptions:
2351      *
2352      * 1. queue_mask indicates the queues which may be involved so that we can
2353      *    properly handle ISR vs normal calling.
2354      *    Set the mask to 0x0000000F to indicate all queues if there is any
2355      *    uncertainty.
2356      *    Set the mask to 0xFFFFFFF0 to indicate we are being called from a GEM
2357      *    ISR.
2358      * 2. We wait for any outstanding transmits on other queues to complete
2359      *    because we need to ALWAYS write to the queue 0 pointer to trigger
2360      *    internal restart of the DMA process.
2361      * 3. We accept at most MSS_MAC_TX_RING_SIZE-1 packets as the final packet
2362      *    in the chain is a dummy one to get the TX DMA engine to stop. Any
2363      *    packets beyond that are silently dropped.
2364      *
2365      * We do transmission by using multiple buffer descriptors. The initial
2366      * descriptors are for the packet(s) to transmit and the last is a dummy one
2367      * with the USED bit set. This halts transmission once the first packet is
2368      * transmitted. We always reset the TX DMA to point to the first packet when
2369      * we send packets so we don't have to juggle buffer positions or worry
2370      * about wrap.
2371      */
2372     volatile int delay;
2373     volatile uint32_t *p_nw_control;
2374     volatile uint32_t *p_tx_status;
2375 
2376     p_nw_control = &this_mac->mac_base->NETWORK_CONTROL;
2377     p_tx_status  = &this_mac->mac_base->TRANSMIT_STATUS;
2378 
2379     /* Wait for queue to empty */
2380     while(this_mac->queue[0].nb_available_tx_desc != (uint32_t)MSS_MAC_TX_RING_SIZE)
2381         {
2382         /* Make sure transmit stays enabled */
2383         if(0 == (*p_nw_control & GEM_ENABLE_TRANSMIT))
2384             {
2385             *p_nw_control = *p_nw_control | GEM_ENABLE_TRANSMIT;
2386             }
2387         }
2388 
2389     PLIC_DisableIRQ(this_mac->mac_q_int[0]); /* Single interrupt from GEM? */
2390 
2391     /*
2392      * Wait for pending transmits to complete as you cannot alter
2393      * tx queue pointers while transmit is active...
2394      */
2395     while(0 != (*p_tx_status & GEM_TRANSMIT_GO))
2396     {
2397         delay++; /* Empty loop will cause debug issues... */
2398     }
2399 
2400     *this_mac->queue[0].transmit_q_ptr = (uint32_t)((uint64_t)this_mac->queue[0].tx_desc_tab) | 1UL;
2401     this_mac->queue[0].tries = 0UL;
2402 
2403     /* All is quiet now so let's construct the TX queue(s) */
2404 
2405     copy8b((uint64_t *)this_mac->queue[0].tx_desc_tab, (uint64_t *)descriptors, sizeof(this_mac->queue[0].tx_desc_tab) / 8);
2406 
2407     this_mac->queue[0].egress += tx_count;
2408 
2409     this_mac->queue[0].nb_available_tx_desc = 1;
2410     this_mac->queue[0].current_tx_desc = 0;
2411     *this_mac->queue[0].transmit_q_ptr = (uint32_t)((uint64_t)&this_mac->queue[0].tx_desc_tab[0]);
2412     *p_nw_control = *p_nw_control | GEM_TRANSMIT_START;
2413 
2414     PLIC_EnableIRQ(this_mac->mac_q_int[0]); /* Single interrupt from GEM? */
2415 
2416     return(MSS_MAC_ERR_OK);
2417 }
2418 
2419 #endif /* defined(MSS_MAC_SPEED_TEST) */
2420 
2421 /******************************************************************************
2422  *
2423  */
2424 #if defined(USING_LWIP)
2425 extern BaseType_t g_mac_context_switch;
2426 #endif
2427 
2428 #if defined(USING_FREERTOS)
2429 extern UBaseType_t uxCriticalNesting;
2430 #endif
2431 #if defined(TARGET_ALOE)
2432 uint8_t  MAC0_plic_53_IRQHandler(void);
MAC0_plic_53_IRQHandler(void)2433 uint8_t  MAC0_plic_53_IRQHandler(void)
2434 {
2435 #if defined(USING_FREERTOS)
2436     uxCriticalNesting++;
2437     generic_mac_irq_handler(&g_mac0, 0U);
2438     uxCriticalNesting--;
2439 #else
2440     generic_mac_irq_handler(&g_mac0, 0U);
2441 #endif
2442     return(EXT_IRQ_KEEP_ENABLED);
2443 }
2444 #else
2445 
2446 
2447 /******************************************************************************
2448  *
2449  */
mac0_int_plic_IRQHandler(void)2450 uint8_t mac0_int_plic_IRQHandler(void)
2451 {
2452 #if defined(USING_FREERTOS)
2453     uxCriticalNesting++;
2454     generic_mac_irq_handler(&g_mac0, 0U);
2455     uxCriticalNesting--;
2456 #else
2457     generic_mac_irq_handler(&g_mac0, 0U);
2458 #endif
2459 
2460     return(EXT_IRQ_KEEP_ENABLED);
2461 }
2462 
2463 
2464 /******************************************************************************
2465  *
2466  */
mac0_queue1_plic_IRQHandler(void)2467 uint8_t mac0_queue1_plic_IRQHandler(void)
2468 {
2469 #if defined(USING_FREERTOS)
2470     uxCriticalNesting++;
2471     generic_mac_irq_handler(&g_mac0, 1U);
2472     uxCriticalNesting--;
2473 #else
2474     generic_mac_irq_handler(&g_mac0, 1U);
2475 #endif
2476     return(EXT_IRQ_KEEP_ENABLED);
2477 }
2478 
2479 
2480 /******************************************************************************
2481  *
2482  */
mac0_queue2_plic_IRQHandler(void)2483 uint8_t mac0_queue2_plic_IRQHandler(void)
2484 {
2485 #if defined(USING_FREERTOS)
2486     uxCriticalNesting++;
2487     generic_mac_irq_handler(&g_mac0, 2U);
2488     uxCriticalNesting--;
2489 #else
2490     generic_mac_irq_handler(&g_mac0, 2U);
2491 #endif
2492     return(EXT_IRQ_KEEP_ENABLED);
2493 }
2494 
2495 
2496 /******************************************************************************
2497  *
2498  */
mac0_queue3_plic_IRQHandler(void)2499 uint8_t mac0_queue3_plic_IRQHandler(void)
2500 {
2501 #if defined(USING_FREERTOS)
2502     uxCriticalNesting++;
2503     generic_mac_irq_handler(&g_mac0, 3U);
2504     uxCriticalNesting--;
2505 #else
2506     generic_mac_irq_handler(&g_mac0, 3U);
2507 #endif
2508     return(EXT_IRQ_KEEP_ENABLED);
2509 }
2510 
2511 
2512 /******************************************************************************
2513  *
2514  */
mac0_emac_plic_IRQHandler(void)2515 uint8_t mac0_emac_plic_IRQHandler(void)
2516 {
2517 #if defined(USING_FREERTOS)
2518     uxCriticalNesting++;
2519     generic_mac_irq_handler(&g_emac0, 0U);
2520     uxCriticalNesting--;
2521 #else
2522     generic_mac_irq_handler(&g_emac0, 0U);
2523 #endif
2524     return(EXT_IRQ_KEEP_ENABLED);
2525 }
2526 
2527 
2528 /******************************************************************************
2529  *
2530  */
mac0_mmsl_plic_IRQHandler(void)2531 uint8_t mac0_mmsl_plic_IRQHandler(void)
2532 {
2533     g_mac0.mac_base->MMSL_INT_DISABLE = 0x3F; /* Acknowledge ints */
2534     return(EXT_IRQ_KEEP_ENABLED);
2535 }
2536 
2537 
2538 
2539 /******************************************************************************
2540  *
2541  */
mac1_int_plic_IRQHandler(void)2542 uint8_t mac1_int_plic_IRQHandler(void)
2543 {
2544 #if defined(USING_FREERTOS)
2545     uxCriticalNesting++;
2546     generic_mac_irq_handler(&g_mac1, 0U);
2547     uxCriticalNesting--;
2548 #else
2549     generic_mac_irq_handler(&g_mac1, 0U);
2550 #endif
2551     return(EXT_IRQ_KEEP_ENABLED);
2552 }
2553 
2554 
2555 /******************************************************************************
2556  *
2557  */
mac1_queue1_plic_IRQHandler(void)2558 uint8_t mac1_queue1_plic_IRQHandler(void)
2559 {
2560 #if defined(USING_FREERTOS)
2561     uxCriticalNesting++;
2562     generic_mac_irq_handler(&g_mac1, 1U);
2563     uxCriticalNesting--;
2564 #else
2565     generic_mac_irq_handler(&g_mac1, 1U);
2566 #endif
2567     return(EXT_IRQ_KEEP_ENABLED);
2568 }
2569 
2570 
2571 /******************************************************************************
2572  *
2573  */
mac1_queue2_plic_IRQHandler(void)2574 uint8_t mac1_queue2_plic_IRQHandler(void)
2575 {
2576 #if defined(USING_FREERTOS)
2577     uxCriticalNesting++;
2578     generic_mac_irq_handler(&g_mac1, 2U);
2579     uxCriticalNesting--;
2580 #else
2581     generic_mac_irq_handler(&g_mac1, 2U);
2582 #endif
2583     return(EXT_IRQ_KEEP_ENABLED);
2584 }
2585 
2586 
2587 /******************************************************************************
2588  *
2589  */
mac1_queue3_plic_IRQHandler(void)2590 uint8_t mac1_queue3_plic_IRQHandler(void)
2591 {
2592 #if defined(USING_FREERTOS)
2593     uxCriticalNesting++;
2594     generic_mac_irq_handler(&g_mac1, 3U);
2595     uxCriticalNesting--;
2596 #else
2597     generic_mac_irq_handler(&g_mac1, 3U);
2598 #endif
2599     return(EXT_IRQ_KEEP_ENABLED);
2600 }
2601 
2602 
2603 /******************************************************************************
2604  *
2605  */
mac1_emac_plic_IRQHandler(void)2606 uint8_t mac1_emac_plic_IRQHandler(void)
2607 {
2608 #if defined(USING_FREERTOS)
2609     uxCriticalNesting++;
2610     generic_mac_irq_handler(&g_emac1, 0U);
2611     uxCriticalNesting--;
2612 #else
2613     generic_mac_irq_handler(&g_emac1, 0U);
2614 #endif
2615     return(EXT_IRQ_KEEP_ENABLED);
2616 }
2617 
2618 
2619 /******************************************************************************
2620  *
2621  */
mac1_mmsl_plic_IRQHandler(void)2622 uint8_t mac1_mmsl_plic_IRQHandler(void)
2623 {
2624     g_mac1.mac_base->MMSL_INT_DISABLE = 0x3F; /* Acknowledge ints */
2625     return(EXT_IRQ_KEEP_ENABLED);
2626 }
2627 
2628 
2629 /******************************************************************************
2630  *
2631  */
2632 /* U54 1 */
mac_mmsl_u54_1_local_IRQHandler_3(void)2633 void mac_mmsl_u54_1_local_IRQHandler_3(void)
2634 {
2635     g_mac0.mac_base->MMSL_INT_DISABLE = 0x3F; /* Acknowledge ints */
2636 }
2637 
2638 
2639 /******************************************************************************
2640  *
2641  */
mac_emac_u54_1_local_IRQHandler_4(void)2642 void mac_emac_u54_1_local_IRQHandler_4(void)
2643 {
2644 #if defined(USING_FREERTOS)
2645     uxCriticalNesting++;
2646     generic_mac_irq_handler(&g_emac0, 0U);
2647     uxCriticalNesting--;
2648 #else
2649     generic_mac_irq_handler(&g_emac0, 0U);
2650 #endif
2651 #if defined(USING_LWIP)
2652     if(0 != g_mac_context_switch)
2653     {
2654         g_mac_context_switch = 0;
2655         vPortYieldISR();
2656     }
2657 #endif
2658 }
2659 
2660 
2661 /******************************************************************************
2662  *
2663  */
mac_queue3_u54_1_local_IRQHandler_5(void)2664 void mac_queue3_u54_1_local_IRQHandler_5(void)
2665 {
2666 #if defined(USING_FREERTOS)
2667     uxCriticalNesting++;
2668     generic_mac_irq_handler(&g_mac0, 3U);
2669     uxCriticalNesting--;
2670 #else
2671     generic_mac_irq_handler(&g_mac0, 3U);
2672 #endif
2673 #if defined(USING_LWIP)
2674     if(0 != g_mac_context_switch)
2675     {
2676         g_mac_context_switch = 0;
2677         vPortYieldISR();
2678     }
2679 #endif
2680 }
2681 
2682 
2683 /******************************************************************************
2684  *
2685  */
mac_queue2_u54_1_local_IRQHandler_6(void)2686 void mac_queue2_u54_1_local_IRQHandler_6(void)
2687 {
2688 #if defined(USING_FREERTOS)
2689     uxCriticalNesting++;
2690     generic_mac_irq_handler(&g_mac0, 2U);
2691     uxCriticalNesting--;
2692 #else
2693     generic_mac_irq_handler(&g_mac0, 2U);
2694 #endif
2695 #if defined(USING_LWIP)
2696     if(0 != g_mac_context_switch)
2697     {
2698         g_mac_context_switch = 0;
2699         vPortYieldISR();
2700     }
2701 #endif
2702 }
2703 
2704 
2705 /******************************************************************************
2706  *
2707  */
mac_queue1_u54_1_local_IRQHandler_7(void)2708 void mac_queue1_u54_1_local_IRQHandler_7(void)
2709 {
2710 #if defined(USING_FREERTOS)
2711     uxCriticalNesting++;
2712     generic_mac_irq_handler(&g_mac0, 1U);
2713     uxCriticalNesting--;
2714 #else
2715     generic_mac_irq_handler(&g_mac0, 1U);
2716 #endif
2717 #if defined(USING_LWIP)
2718     if(0 != g_mac_context_switch)
2719     {
2720         g_mac_context_switch = 0;
2721         vPortYieldISR();
2722     }
2723 #endif
2724 }
2725 
2726 
2727 /******************************************************************************
2728  *
2729  */
mac_int_u54_1_local_IRQHandler_8(void)2730 void mac_int_u54_1_local_IRQHandler_8(void)
2731 {
2732 #if defined(USING_FREERTOS)
2733     uxCriticalNesting++;
2734     generic_mac_irq_handler(&g_mac0, 0U);
2735     uxCriticalNesting--;
2736 #else
2737     generic_mac_irq_handler(&g_mac0, 0U);
2738 #endif
2739 #if defined(USING_LWIP)
2740     if(0 != g_mac_context_switch)
2741     {
2742         g_mac_context_switch = 0;
2743         vPortYieldISR();
2744     }
2745 #endif
2746 }
2747 
2748 
2749 /******************************************************************************
2750  *
2751  */
2752 /* U54 2 */
mac_mmsl_u54_2_local_IRQHandler_3(void)2753 void mac_mmsl_u54_2_local_IRQHandler_3(void)
2754 {
2755     g_mac0.mac_base->MMSL_INT_DISABLE = 0x3F; /* Acknowledge ints */
2756 }
2757 
2758 
2759 /******************************************************************************
2760  *
2761  */
mac_emac_u54_2_local_IRQHandler_4(void)2762 void mac_emac_u54_2_local_IRQHandler_4(void)
2763 {
2764 #if defined(USING_FREERTOS)
2765     uxCriticalNesting++;
2766     generic_mac_irq_handler(&g_emac0, 0U);
2767     uxCriticalNesting--;
2768 #else
2769     generic_mac_irq_handler(&g_emac0, 0U);
2770 #endif
2771 #if defined(USING_LWIP)
2772     if(0 != g_mac_context_switch)
2773     {
2774         g_mac_context_switch = 0;
2775         vPortYieldISR();
2776     }
2777 #endif
2778 }
2779 
2780 
2781 /******************************************************************************
2782  *
2783  */
mac_queue3_u54_2_local_IRQHandler_5(void)2784 void mac_queue3_u54_2_local_IRQHandler_5(void)
2785 {
2786 #if defined(USING_FREERTOS)
2787     uxCriticalNesting++;
2788     generic_mac_irq_handler(&g_mac0, 3U);
2789     uxCriticalNesting--;
2790 #else
2791     generic_mac_irq_handler(&g_mac0, 3U);
2792 #endif
2793 #if defined(USING_LWIP)
2794     if(0 != g_mac_context_switch)
2795     {
2796         g_mac_context_switch = 0;
2797         vPortYieldISR();
2798     }
2799 #endif
2800 }
2801 
2802 
2803 /******************************************************************************
2804  *
2805  */
mac_queue2_u54_2_local_IRQHandler_6(void)2806 void mac_queue2_u54_2_local_IRQHandler_6(void)
2807 {
2808 #if defined(USING_FREERTOS)
2809     uxCriticalNesting++;
2810     generic_mac_irq_handler(&g_mac0, 2U);
2811     uxCriticalNesting--;
2812 #else
2813     generic_mac_irq_handler(&g_mac0, 2U);
2814 #endif
2815 #if defined(USING_LWIP)
2816     if(0 != g_mac_context_switch)
2817     {
2818         g_mac_context_switch = 0;
2819         vPortYieldISR();
2820     }
2821 #endif
2822 }
2823 
2824 
2825 /******************************************************************************
2826  *
2827  */
mac_queue1_u54_2_local_IRQHandler_7(void)2828 void mac_queue1_u54_2_local_IRQHandler_7(void)
2829 {
2830 #if defined(USING_FREERTOS)
2831     uxCriticalNesting++;
2832     generic_mac_irq_handler(&g_mac0, 1U);
2833     uxCriticalNesting--;
2834 #else
2835     generic_mac_irq_handler(&g_mac0, 1U);
2836 #endif
2837 #if defined(USING_LWIP)
2838     if(0 != g_mac_context_switch)
2839     {
2840         g_mac_context_switch = 0;
2841         vPortYieldISR();
2842     }
2843 #endif
2844 }
2845 
2846 
2847 /******************************************************************************
2848  *
2849  */
mac_int_u54_2_local_IRQHandler_8(void)2850 void mac_int_u54_2_local_IRQHandler_8(void)
2851 {
2852 #if defined(USING_FREERTOS)
2853     uxCriticalNesting++;
2854     generic_mac_irq_handler(&g_mac0, 0U);
2855     uxCriticalNesting--;
2856 #else
2857     generic_mac_irq_handler(&g_mac0, 0U);
2858 #endif
2859 #if defined(USING_LWIP)
2860     if(0 != g_mac_context_switch)
2861     {
2862         g_mac_context_switch = 0;
2863         vPortYieldISR();
2864     }
2865 #endif
2866 }
2867 
2868 
2869 /******************************************************************************
2870  *
2871  */
2872 /* U54 3 */
mac_mmsl_u54_3_local_IRQHandler_3(void)2873 void mac_mmsl_u54_3_local_IRQHandler_3(void)
2874 {
2875     g_mac1.mac_base->MMSL_INT_DISABLE = 0x3F; /* Acknowledge ints */
2876 }
2877 
2878 
2879 /******************************************************************************
2880  *
2881  */
mac_emac_u54_3_local_IRQHandler_4(void)2882 void mac_emac_u54_3_local_IRQHandler_4(void)
2883 {
2884 #if defined(USING_FREERTOS)
2885     uxCriticalNesting++;
2886     generic_mac_irq_handler(&g_emac1, 0U);
2887     uxCriticalNesting--;
2888 #else
2889     generic_mac_irq_handler(&g_emac1, 0U);
2890 #endif
2891 #if defined(USING_LWIP)
2892     if(0 != g_mac_context_switch)
2893     {
2894         g_mac_context_switch = 0;
2895         vPortYieldISR();
2896     }
2897 #endif
2898 }
2899 
2900 
2901 /******************************************************************************
2902  *
2903  */
mac_queue3_u54_3_local_IRQHandler_5(void)2904 void mac_queue3_u54_3_local_IRQHandler_5(void)
2905 {
2906 #if defined(USING_FREERTOS)
2907     uxCriticalNesting++;
2908     generic_mac_irq_handler(&g_mac1, 3U);
2909     uxCriticalNesting--;
2910 #else
2911     generic_mac_irq_handler(&g_mac1, 3U);
2912 #endif
2913 #if defined(USING_LWIP)
2914     if(0 != g_mac_context_switch)
2915     {
2916         g_mac_context_switch = 0;
2917         vPortYieldISR();
2918     }
2919 #endif
2920 }
2921 
2922 
2923 /******************************************************************************
2924  *
2925  */
mac_queue2_u54_3_local_IRQHandler_6(void)2926 void mac_queue2_u54_3_local_IRQHandler_6(void)
2927 {
2928 #if defined(USING_FREERTOS)
2929     uxCriticalNesting++;
2930     generic_mac_irq_handler(&g_mac1, 2U);
2931     uxCriticalNesting--;
2932 #else
2933     generic_mac_irq_handler(&g_mac1, 2U);
2934 #endif
2935 #if defined(USING_LWIP)
2936     if(0 != g_mac_context_switch)
2937     {
2938         g_mac_context_switch = 0;
2939         vPortYieldISR();
2940     }
2941 #endif
2942 }
2943 
2944 
2945 /******************************************************************************
2946  *
2947  */
mac_queue1_u54_3_local_IRQHandler_7(void)2948 void mac_queue1_u54_3_local_IRQHandler_7(void)
2949 {
2950 #if defined(USING_FREERTOS)
2951     uxCriticalNesting++;
2952     generic_mac_irq_handler(&g_mac1, 1U);
2953     uxCriticalNesting--;
2954 #else
2955     generic_mac_irq_handler(&g_mac1, 1U);
2956 #endif
2957 #if defined(USING_LWIP)
2958     if(0 != g_mac_context_switch)
2959     {
2960         g_mac_context_switch = 0;
2961         vPortYieldISR();
2962     }
2963 #endif
2964 }
2965 
2966 
2967 /******************************************************************************
2968  *
2969  */
mac_int_u54_3_local_IRQHandler_8(void)2970 void mac_int_u54_3_local_IRQHandler_8(void)
2971 {
2972 #if defined(USING_FREERTOS)
2973     uxCriticalNesting++;
2974     generic_mac_irq_handler(&g_mac1, 0U);
2975     uxCriticalNesting--;
2976 #else
2977     generic_mac_irq_handler(&g_mac1, 0U);
2978 #endif
2979 #if defined(USING_LWIP)
2980     if(0 != g_mac_context_switch)
2981     {
2982         g_mac_context_switch = 0;
2983         vPortYieldISR();
2984     }
2985 #endif
2986 }
2987 
2988 
2989 /******************************************************************************
2990  *
2991  */
2992 /* U54 4 */
mac_mmsl_u54_4_local_IRQHandler_3(void)2993 void mac_mmsl_u54_4_local_IRQHandler_3(void)
2994 {
2995     g_mac1.mac_base->MMSL_INT_DISABLE = 0x3F; /* Acknowledge ints */
2996 }
2997 
2998 
2999 /******************************************************************************
3000  *
3001  */
mac_emac_u54_4_local_IRQHandler_4(void)3002 void mac_emac_u54_4_local_IRQHandler_4(void)
3003 {
3004 #if defined(USING_FREERTOS)
3005     uxCriticalNesting++;
3006     generic_mac_irq_handler(&g_emac1, 0U);
3007     uxCriticalNesting--;
3008 #else
3009     generic_mac_irq_handler(&g_emac1, 0U);
3010 #endif
3011 #if defined(USING_LWIP)
3012     if(0 != g_mac_context_switch)
3013     {
3014         g_mac_context_switch = 0;
3015         vPortYieldISR();
3016     }
3017 #endif
3018 }
3019 
3020 
3021 /******************************************************************************
3022  *
3023  */
mac_queue3_u54_4_local_IRQHandler_5(void)3024 void mac_queue3_u54_4_local_IRQHandler_5(void)
3025 {
3026 #if defined(USING_FREERTOS)
3027     uxCriticalNesting++;
3028     generic_mac_irq_handler(&g_mac1, 3U);
3029     uxCriticalNesting--;
3030 #else
3031     generic_mac_irq_handler(&g_mac1, 3U);
3032 #endif
3033 #if defined(USING_LWIP)
3034     if(0 != g_mac_context_switch)
3035     {
3036         g_mac_context_switch = 0;
3037         vPortYieldISR();
3038     }
3039 #endif
3040 }
3041 
3042 
3043 /******************************************************************************
3044  *
3045  */
mac_queue2_u54_4_local_IRQHandler_6(void)3046 void mac_queue2_u54_4_local_IRQHandler_6(void)
3047 {
3048 #if defined(USING_FREERTOS)
3049     uxCriticalNesting++;
3050     generic_mac_irq_handler(&g_mac1, 2U);
3051     uxCriticalNesting--;
3052 #else
3053     generic_mac_irq_handler(&g_mac1, 2U);
3054 #endif
3055 #if defined(USING_LWIP)
3056     if(0 != g_mac_context_switch)
3057     {
3058         g_mac_context_switch = 0;
3059         vPortYieldISR();
3060     }
3061 #endif
3062 }
3063 
3064 
3065 /******************************************************************************
3066  *
3067  */
mac_queue1_u54_4_local_IRQHandler_7(void)3068 void mac_queue1_u54_4_local_IRQHandler_7(void)
3069 {
3070 #if defined(USING_FREERTOS)
3071     uxCriticalNesting++;
3072     generic_mac_irq_handler(&g_mac1, 1U);
3073     uxCriticalNesting--;
3074 #else
3075     generic_mac_irq_handler(&g_mac1, 1U);
3076 #endif
3077 #if defined(USING_LWIP)
3078     if(0 != g_mac_context_switch)
3079     {
3080         g_mac_context_switch = 0;
3081         vPortYieldISR();
3082     }
3083 #endif
3084 }
3085 
3086 
3087 /******************************************************************************
3088  *
3089  */
mac_int_u54_4_local_IRQHandler_8(void)3090 void mac_int_u54_4_local_IRQHandler_8(void)
3091 {
3092 #if defined(USING_FREERTOS)
3093     uxCriticalNesting++;
3094     generic_mac_irq_handler(&g_mac1, 0U);
3095     uxCriticalNesting--;
3096 #else
3097     generic_mac_irq_handler(&g_mac1, 0U);
3098 #endif
3099 #if defined(USING_LWIP)
3100     if(0 != g_mac_context_switch)
3101     {
3102         g_mac_context_switch = 0;
3103         vPortYieldISR();
3104     }
3105 #endif
3106 }
3107 
3108 #endif
3109 
3110 
3111 /* Define the following if your GEM is configured to clear on read for int flags
3112  * In this case you should not write to the int status reg ... */
3113 /* #define GEM_FLAGS_CLR_ON_RD */
3114 
generic_mac_irq_handler(mss_mac_instance_t * this_mac,uint64_t queue_no)3115 static void generic_mac_irq_handler(mss_mac_instance_t *this_mac, uint64_t queue_no)
3116 {
3117     volatile uint32_t int_pending;  /* We read and hold a working copy as many
3118                                      * of the bits can be clear on read if
3119                                      * the GEM is configured that way... */
3120     uint32_t volatile *rx_status;   /* Address of receive status register */
3121     uint32_t volatile *tx_status;   /* Address of transmit status register */
3122     uint32_t volatile *int_status;  /* Address of interrupt status register */
3123     mss_mac_queue_t *p_queue;
3124 
3125     p_queue = &this_mac->queue[queue_no];
3126 
3127     p_queue->in_isr = 1U;
3128     int_status  = p_queue->int_status;
3129     int_pending =  *int_status;
3130 
3131     if(0U != this_mac->is_emac)
3132     {
3133         rx_status   = &this_mac->emac_base->RECEIVE_STATUS;
3134         tx_status   = &this_mac->emac_base->TRANSMIT_STATUS;
3135     }
3136     else
3137     {
3138         rx_status   = &this_mac->mac_base->RECEIVE_STATUS;
3139         tx_status   = &this_mac->mac_base->TRANSMIT_STATUS;
3140     }
3141 
3142     /*
3143      * Note, in the following code we generally clear any flags first and then
3144      * handle the condition as this allows any new events which occur in the
3145      * course of the ISR to be picked up later.
3146      */
3147 
3148     /*
3149      * Packet received interrupt - first in line as most time critical. Followed
3150      * by transmit interrupt and then the less frequent ones.
3151      */
3152     if((int_pending & GEM_RECEIVE_COMPLETE) != 0U)
3153     {
3154        *rx_status = GEM_FRAME_RECEIVED;
3155 #if !defined(GEM_FLAGS_CLR_ON_RD)
3156 #if defined(TARGET_ALOE)
3157         *int_status = (uint32_t)3U; /* PMCS: Should be 2 but that does not work on Aloe... */
3158 #else
3159         *int_status = (uint32_t)2U;
3160 #endif
3161         rxpkt_handler(this_mac, queue_no);
3162         p_queue->overflow_counter = 0U; /* Reset counter as we have received something */
3163 #endif
3164     }
3165 
3166     /* Transmit packet sent interrupt */
3167     if((int_pending & GEM_TRANSMIT_COMPLETE) != 0U)
3168     {
3169         if((*tx_status & GEM_STAT_TRANSMIT_COMPLETE) != 0U) /* If loopback test or other hasn't taken care of this... */
3170         {
3171             *tx_status  = GEM_STAT_TRANSMIT_COMPLETE;
3172             *int_status = GEM_TRANSMIT_COMPLETE;
3173 #if !defined(GEM_FLAGS_CLR_ON_RD)
3174 #endif
3175             txpkt_handler(this_mac, queue_no);
3176         }
3177     }
3178 
3179     /*
3180      * RX and TX are the majority cases so see if all done rather than testing
3181      * remaining one by one. Move on to one by one testing if not finished. Cuts
3182      * down on interrupt processing impact for 'normal' case...
3183      */
3184     if((int_pending & ~(GEM_RECEIVE_COMPLETE | GEM_TRANSMIT_COMPLETE)) != 0U)
3185     {
3186         if((int_pending & GEM_RECEIVE_OVERRUN_INT) != 0U)
3187         {
3188             *rx_status = GEM_RECEIVE_OVERRUN;
3189 #if !defined(GEM_FLAGS_CLR_ON_RD)
3190             *int_status = GEM_RECEIVE_OVERRUN_INT;
3191 #endif
3192             p_queue->overflow_counter++;
3193             p_queue->rx_overflow++;
3194         }
3195 
3196         if((int_pending & GEM_RX_USED_BIT_READ) != 0U)
3197         {
3198             *rx_status = GEM_BUFFER_NOT_AVAILABLE;
3199     #if !defined(GEM_FLAGS_CLR_ON_RD)
3200             *int_status = GEM_RX_USED_BIT_READ;
3201     #endif
3202             rxpkt_handler(this_mac, queue_no);
3203             p_queue->rx_overflow++;
3204             p_queue->overflow_counter++;
3205         }
3206 
3207         if((int_pending & GEM_RESP_NOT_OK_INT) != 0U) /* Hope this is transient and restart rx... */
3208         {
3209             *rx_status = GEM_RX_RESP_NOT_OK; /* One of them did it... */
3210             *tx_status = GEM_TX_RESP_NOT_OK;
3211     #if !defined(GEM_FLAGS_CLR_ON_RD)
3212             *int_status = GEM_RESP_NOT_OK_INT;
3213     #endif
3214             if(0U != this_mac->is_emac)
3215             {
3216                 this_mac->emac_base->NETWORK_CONTROL |= GEM_ENABLE_RECEIVE;
3217             }
3218             else
3219             {
3220                 this_mac->mac_base->NETWORK_CONTROL |= GEM_ENABLE_RECEIVE;
3221             }
3222 
3223             p_queue->hresp_error++;
3224         }
3225 
3226     /*
3227      * This may cause more problems than it cures so disabling for now until we
3228      * figure out a better strategy...
3229      */
3230     #if 0
3231         if(p_queue->overflow_counter > 4U) /* looks like we are stuck in a rut here... */
3232         {
3233             uint32_t descriptor;
3234             /* Restart receive operation from scratch */
3235             p_queue->overflow_counter = 0U;
3236             p_queue->rx_restart++;
3237 
3238             if(0U != this_mac->is_emac)
3239             {
3240                 this_mac->emac_base->NETWORK_CONTROL &= ~GEM_ENABLE_RECEIVE;
3241             }
3242             else
3243             {
3244                 this_mac->mac_base->NETWORK_CONTROL &= ~GEM_ENABLE_RECEIVE;
3245             }
3246 
3247             p_queue->nb_available_rx_desc = MSS_MAC_RX_RING_SIZE;
3248             p_queue->next_free_rx_desc_index = 0U;
3249             p_queue->first_rx_desc_index = 0U;
3250 
3251             for(descriptor = 0U; descriptor < MSS_MAC_RX_RING_SIZE; descriptor++) /* Discard everything */
3252             {
3253                 p_queue->rx_desc_tab[descriptor].addr_low &= ~GEM_RX_DMA_USED;
3254             }
3255 
3256             if(0U != this_mac->is_emac)
3257             {
3258                 this_mac->emac_base->RECEIVE_Q_PTR = (uint32_t)((uint64_t)p_queue->rx_desc_tab);
3259     #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
3260                 this_mac->emac_base->UPPER_RX_Q_BASE_ADDR = (uint32_t)((uint64_t)p_queue->rx_desc_tab >> 32);
3261     #endif
3262                 this_mac->emac_base->NETWORK_CONTROL |= GEM_ENABLE_RECEIVE;
3263             }
3264             else
3265             {
3266                 this_mac->mac_base->RECEIVE_Q_PTR = (uint32_t)((uint64_t)p_queue->rx_desc_tab);
3267     #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
3268                 this_mac->mac_base->UPPER_RX_Q_BASE_ADDR = (uint32_t)((uint64_t)p_queue->rx_desc_tab >> 32);
3269     #endif
3270                 this_mac->mac_base->NETWORK_CONTROL |= GEM_ENABLE_RECEIVE;
3271             }
3272         }
3273     #endif
3274         if((int_pending & GEM_PAUSE_FRAME_TRANSMITTED) != 0U)
3275         {
3276             *int_status = GEM_PAUSE_FRAME_TRANSMITTED;
3277             this_mac->tx_pause++;
3278         }
3279         if((int_pending & GEM_PAUSE_TIME_ELAPSED) != 0U)
3280         {
3281             *int_status = GEM_PAUSE_TIME_ELAPSED;
3282             this_mac->pause_elapsed++;
3283         }
3284         if((int_pending & GEM_PAUSE_FRAME_WITH_NON_0_PAUSE_QUANTUM_RX) != 0U)
3285         {
3286             *int_status = GEM_PAUSE_FRAME_WITH_NON_0_PAUSE_QUANTUM_RX;
3287             this_mac->rx_pause++;
3288         }
3289 
3290         /* Mask off checked ints and see if any left pending */
3291         int_pending &= ~(GEM_RECEIVE_OVERRUN_INT | GEM_RX_USED_BIT_READ | GEM_RECEIVE_COMPLETE |
3292                          GEM_TRANSMIT_COMPLETE | GEM_RESP_NOT_OK_INT | GEM_PAUSE_FRAME_TRANSMITTED |
3293                          GEM_PAUSE_TIME_ELAPSED | GEM_PAUSE_FRAME_WITH_NON_0_PAUSE_QUANTUM_RX);
3294         if(0U != int_pending)
3295         {
3296             if((int_pending & GEM_AMBA_ERROR) != 0U)
3297             {
3298                 /* *int_status = (uint32_t)0x60U; */ /* Should be 0x40 but that doesn't clear it... */
3299                 *int_status = (uint32_t)0x40U;
3300                 *tx_status  = GEM_STAT_AMBA_ERROR;
3301                 *rx_status  = GEM_AMBA_ERROR;
3302                 p_queue->tx_amba_errors++;
3303                 p_queue->nb_available_tx_desc = MSS_MAC_TX_RING_SIZE;
3304             }
3305             else
3306             {
3307                 volatile int32_t index;
3308                 ASSERT(0); /* Need to think about how to deal with this... */
3309                 while(1)
3310                 {
3311                     index++;
3312                 }
3313             }
3314         }
3315     }
3316     p_queue->in_isr = 0U;
3317 }
3318 
3319 
3320 /******************************************************************************
3321  * See mss_ethernet_mac.h for details of how to use this function.
3322  */
MSS_MAC_set_tx_callback(mss_mac_instance_t * this_mac,uint32_t queue_no,mss_mac_transmit_callback_t tx_complete_handler)3323 void MSS_MAC_set_tx_callback
3324 (
3325     mss_mac_instance_t *this_mac,
3326     uint32_t queue_no,
3327     mss_mac_transmit_callback_t tx_complete_handler
3328 )
3329 {
3330     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3331     {
3332         this_mac->queue[queue_no].pckt_tx_callback = tx_complete_handler;
3333     }
3334 }
3335 
3336 
3337 /******************************************************************************
3338  * See mss_ethernet_mac.h for details of how to use this function.
3339  */
MSS_MAC_set_rx_callback(mss_mac_instance_t * this_mac,uint32_t queue_no,mss_mac_receive_callback_t rx_callback)3340 void MSS_MAC_set_rx_callback
3341 (
3342     mss_mac_instance_t *this_mac,
3343     uint32_t queue_no,
3344     mss_mac_receive_callback_t rx_callback
3345 )
3346 {
3347     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3348     {
3349         this_mac->queue[queue_no].pckt_rx_callback = rx_callback;
3350     }
3351 }
3352 
3353 
3354 /******************************************************************************
3355  * See mss_ethernet_mac.h for details of how to use this function.
3356  */
MSS_MAC_change_speed(mss_mac_instance_t * this_mac,uint32_t speed_duplex_select,mss_mac_speed_mode_t speed_mode)3357 void MSS_MAC_change_speed
3358 (
3359     mss_mac_instance_t *this_mac, uint32_t speed_duplex_select, mss_mac_speed_mode_t speed_mode
3360 )
3361 {
3362     uint32_t temp_cr;
3363 
3364     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3365     {
3366         /* Only change HW settings if there is a change in status */
3367         if((this_mac->speed_duplex_select |= speed_duplex_select) || (this_mac->speed_mode != speed_mode))
3368         {
3369             this_mac->speed_duplex_select = speed_duplex_select;
3370             this_mac->speed_mode = speed_mode;
3371 
3372             /* Apply settings to the PHY */
3373             this_mac->phy_set_link_speed(this_mac, this_mac->speed_duplex_select, speed_mode);
3374             this_mac->phy_autonegotiate(this_mac); /* Do this in case it is needed */
3375             if(MSS_MAC_SPEED_AN == speed_mode) /* Apply results of AN to MAC */
3376             {
3377                 update_mac_cfg(this_mac);
3378             }
3379             else
3380             {
3381                 if(0U != this_mac->is_emac)
3382                 {
3383                     temp_cr = this_mac->emac_base->NETWORK_CONFIG;
3384                 }
3385                 else
3386                 {
3387                     temp_cr = this_mac->mac_base->NETWORK_CONFIG;
3388                 }
3389 
3390                 temp_cr &= ~(GEM_GIGABIT_MODE_ENABLE | GEM_SPEED | GEM_FULL_DUPLEX);
3391 
3392                 if((MSS_MAC_1000_HDX == this_mac->speed_mode) || (MSS_MAC_1000_FDX == this_mac->speed_mode))
3393                 {
3394     #if defined(TARGET_ALOE)
3395                     *GEMGXL_tx_clk_sel = (uint32_t)0U;
3396                     *GEMGXL_speed_mode = (uint32_t)2U;
3397     #endif
3398                     temp_cr |= GEM_GIGABIT_MODE_ENABLE;
3399                 }
3400                 else
3401                 {
3402                     if((MSS_MAC_100_HDX == this_mac->speed_mode) || (MSS_MAC_100_FDX == this_mac->speed_mode))
3403                     {
3404     #if defined(TARGET_ALOE)
3405                     *GEMGXL_tx_clk_sel = (uint32_t)1U;
3406                     *GEMGXL_speed_mode = (uint32_t)1U;
3407     #endif
3408                     temp_cr |= (uint32_t)GEM_SPEED;
3409                     }
3410     #if defined(TARGET_ALOE)
3411                     else
3412                     {
3413                         *GEMGXL_tx_clk_sel = (uint32_t)1U;
3414                         *GEMGXL_speed_mode = (uint32_t)0U;
3415                     }
3416     #endif
3417                 }
3418 
3419                 /* Configure duplex mode */
3420                 if((MSS_MAC_10_FDX == this_mac->speed_mode) || (MSS_MAC_100_FDX == this_mac->speed_mode) || (MSS_MAC_1000_FDX == this_mac->speed_mode))
3421                 {
3422                     temp_cr |= GEM_FULL_DUPLEX;
3423                 }
3424 
3425                 if(0U != this_mac->is_emac)
3426                 {
3427                     this_mac->emac_base->NETWORK_CONFIG = temp_cr;
3428                 }
3429                 else
3430                 {
3431                     this_mac->mac_base->NETWORK_CONFIG = temp_cr;
3432                 }
3433             }
3434         }
3435     }
3436 }
3437 
3438 
3439 /******************************************************************************
3440  * See mss_ethernet_mac.h for details of how to use this function.
3441  */
3442 
MSS_MAC_init_TSU(const mss_mac_instance_t * this_mac,const mss_mac_tsu_config_t * tsu_cfg)3443 void MSS_MAC_init_TSU(const mss_mac_instance_t *this_mac, const mss_mac_tsu_config_t *tsu_cfg)
3444 {
3445     uint32_t temp;
3446 
3447     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3448     {
3449         temp  = (tsu_cfg->sub_ns_inc & 0xFFU) << 24;
3450         temp |= (tsu_cfg->sub_ns_inc >> 8) & 0xFFFFU;
3451 
3452         if(0U != this_mac->is_emac)
3453         {
3454 #if 0 /* Shouldn't really allow setting of tsu through eMAC as it is slaved to pMAC TSU */
3455             this_mac->emac_base->TSU_TIMER_INCR_SUB_NSEC = temp;
3456             this_mac->emac_base->TSU_TIMER_INCR          = tsu_cfg->ns_inc;
3457 
3458             /* PMCS: I'm not 100% sure about the sequencing here... */
3459 
3460             this_mac->emac_base->TSU_TIMER_MSB_SEC       = tsu_cfg->secs_msb;
3461             this_mac->emac_base->TSU_TIMER_SEC           = tsu_cfg->secs_lsb;
3462             this_mac->emac_base->TSU_TIMER_NSEC          = tsu_cfg->nanoseconds;
3463 #endif
3464         }
3465         else
3466         {
3467             this_mac->mac_base->TSU_TIMER_INCR_SUB_NSEC = temp;
3468             this_mac->mac_base->TSU_TIMER_INCR          = tsu_cfg->ns_inc;
3469             this_mac->mac_base->TSU_TIMER_MSB_SEC       = tsu_cfg->secs_msb;
3470             this_mac->mac_base->TSU_TIMER_SEC           = tsu_cfg->secs_lsb;
3471             this_mac->mac_base->TSU_TIMER_NSEC          = tsu_cfg->nanoseconds;
3472         }
3473     }
3474 }
3475 
3476 
3477 /******************************************************************************
3478  * See mss_ethernet_mac.h for details of how to use this function.
3479  */
3480 
MSS_MAC_read_TSU(const mss_mac_instance_t * this_mac,mss_mac_tsu_time_t * tsu_time)3481 void MSS_MAC_read_TSU(const mss_mac_instance_t *this_mac, mss_mac_tsu_time_t *tsu_time)
3482 {
3483     int32_t got_time = 0;
3484 
3485     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3486     {
3487         do
3488         {
3489             if(0U != this_mac->is_emac)
3490             {
3491                 tsu_time->secs_lsb    = this_mac->emac_base->TSU_TIMER_SEC;
3492                 tsu_time->secs_msb    = this_mac->emac_base->TSU_TIMER_MSB_SEC;
3493                 tsu_time->nanoseconds = this_mac->emac_base->TSU_TIMER_NSEC;
3494 
3495                 /* Check for nanoseconds roll over and exit loop if none otherwise do again */
3496                 if(tsu_time->secs_lsb == this_mac->emac_base->TSU_TIMER_SEC)
3497                 {
3498                     got_time = 1;
3499                 }
3500             }
3501             else
3502             {
3503                 tsu_time->secs_lsb    = this_mac->mac_base->TSU_TIMER_SEC;
3504                 tsu_time->secs_msb    = this_mac->mac_base->TSU_TIMER_MSB_SEC;
3505                 tsu_time->nanoseconds = this_mac->mac_base->TSU_TIMER_NSEC;
3506 
3507                 /* Check for nanoseconds roll over and exit loop if none otherwise do again */
3508                 if(tsu_time->secs_lsb == this_mac->mac_base->TSU_TIMER_SEC)
3509                 {
3510                     got_time = 1;
3511                 }
3512             }
3513         } while(0 == got_time);
3514     }
3515 }
3516 
3517 
3518 /******************************************************************************
3519  * See mss_ethernet_mac.h for details of how to use this function.
3520  */
3521 
MSS_MAC_set_TSU_rx_mode(const mss_mac_instance_t * this_mac,mss_mac_tsu_mode_t tsu_mode)3522 void MSS_MAC_set_TSU_rx_mode(const mss_mac_instance_t *this_mac, mss_mac_tsu_mode_t tsu_mode)
3523 {
3524     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3525     {
3526         if(0U != this_mac->is_emac)
3527         {
3528             this_mac->emac_base->RX_BD_CONTROL = ((uint32_t)tsu_mode << GEM_BD_TS_MODE_SHIFT) & GEM_BD_TS_MODE;
3529         }
3530         else
3531         {
3532             this_mac->mac_base->RX_BD_CONTROL = ((uint32_t)tsu_mode << GEM_BD_TS_MODE_SHIFT) & GEM_BD_TS_MODE;
3533         }
3534     }
3535 }
3536 
3537 
3538 /******************************************************************************
3539  * See mss_ethernet_mac.h for details of how to use this function.
3540  */
3541 
MSS_MAC_set_TSU_tx_mode(const mss_mac_instance_t * this_mac,mss_mac_tsu_mode_t tsu_mode)3542 void MSS_MAC_set_TSU_tx_mode(const mss_mac_instance_t *this_mac, mss_mac_tsu_mode_t tsu_mode)
3543 {
3544     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3545     {
3546         if(0U != this_mac->is_emac)
3547         {
3548             this_mac->emac_base->TX_BD_CONTROL = ((uint32_t)tsu_mode << GEM_BD_TS_MODE_SHIFT) & GEM_BD_TS_MODE;
3549         }
3550         else
3551         {
3552             this_mac->mac_base->TX_BD_CONTROL = ((uint32_t)tsu_mode << GEM_BD_TS_MODE_SHIFT) & GEM_BD_TS_MODE;
3553         }
3554     }
3555 }
3556 
3557 
3558 /******************************************************************************
3559  * See mss_ethernet_mac.h for details of how to use this function.
3560  */
3561 
MSS_MAC_get_TSU_rx_mode(const mss_mac_instance_t * this_mac)3562 mss_mac_tsu_mode_t MSS_MAC_get_TSU_rx_mode(const mss_mac_instance_t *this_mac)
3563 {
3564     mss_mac_tsu_mode_t ret_val = MSS_MAC_TSU_MODE_DISABLED;
3565 
3566     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3567     {
3568         if(0U != this_mac->is_emac)
3569         {
3570             ret_val = (mss_mac_tsu_mode_t)((this_mac->emac_base->RX_BD_CONTROL & GEM_BD_TS_MODE) >> GEM_BD_TS_MODE_SHIFT);
3571         }
3572         else
3573         {
3574             ret_val = (mss_mac_tsu_mode_t)((this_mac->mac_base->RX_BD_CONTROL & GEM_BD_TS_MODE) >> GEM_BD_TS_MODE_SHIFT);
3575         }
3576     }
3577 
3578     return(ret_val);
3579 }
3580 
3581 
3582 /******************************************************************************
3583  * See mss_ethernet_mac.h for details of how to use this function.
3584  */
3585 
MSS_MAC_get_TSU_tx_mode(const mss_mac_instance_t * this_mac)3586 mss_mac_tsu_mode_t MSS_MAC_get_TSU_tx_mode(const mss_mac_instance_t *this_mac)
3587 {
3588     mss_mac_tsu_mode_t ret_val= MSS_MAC_TSU_MODE_DISABLED;
3589 
3590     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3591     {
3592         if(0U != this_mac->is_emac)
3593         {
3594             ret_val = (mss_mac_tsu_mode_t)((this_mac->emac_base->TX_BD_CONTROL & GEM_BD_TS_MODE) >> GEM_BD_TS_MODE_SHIFT);
3595         }
3596         else
3597         {
3598             ret_val = (mss_mac_tsu_mode_t)((this_mac->mac_base->TX_BD_CONTROL & GEM_BD_TS_MODE) >> GEM_BD_TS_MODE_SHIFT);
3599         }
3600     }
3601 
3602     return(ret_val);
3603 }
3604 
3605 
3606 /******************************************************************************
3607  * See mss_ethernet_mac.h for details of how to use this function.
3608  */
3609 
MSS_MAC_set_TSU_oss_mode(const mss_mac_instance_t * this_mac,mss_mac_oss_mode_t oss_mode)3610 void MSS_MAC_set_TSU_oss_mode(const mss_mac_instance_t *this_mac, mss_mac_oss_mode_t oss_mode)
3611 {
3612     volatile uint32_t temp_control;
3613 
3614     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3615     {
3616         if(0U != this_mac->is_emac)
3617         {
3618             temp_control = this_mac->emac_base->NETWORK_CONTROL;
3619         }
3620         else
3621         {
3622             temp_control = this_mac->mac_base->NETWORK_CONTROL;
3623         }
3624 
3625         /*
3626          * Note. The docs don't say these are mutually exclusive but I don't think
3627          * it makes sense to allow both modes at once...
3628          */
3629         if(MSS_MAC_OSS_MODE_DISABLED == oss_mode)
3630         {
3631             temp_control &= ~(GEM_OSS_CORRECTION_FIELD | GEM_ONE_STEP_SYNC_MODE);
3632         }
3633         else if(MSS_MAC_OSS_MODE_REPLACE == oss_mode)
3634         {
3635             temp_control &= ~GEM_OSS_CORRECTION_FIELD;
3636             temp_control |= GEM_ONE_STEP_SYNC_MODE;
3637         }
3638         else
3639         {
3640             if(MSS_MAC_OSS_MODE_ADJUST == oss_mode)
3641             {
3642                 temp_control |= GEM_OSS_CORRECTION_FIELD;
3643                 temp_control &= ~GEM_ONE_STEP_SYNC_MODE;
3644             }
3645         }
3646 
3647         if(0U != this_mac->is_emac)
3648         {
3649             this_mac->emac_base->NETWORK_CONTROL = temp_control;
3650         }
3651         else
3652         {
3653             this_mac->mac_base->NETWORK_CONTROL = temp_control;
3654         }
3655     }
3656 }
3657 
3658 
3659 /******************************************************************************
3660  * See mss_ethernet_mac.h for details of how to use this function.
3661  */
3662 
MSS_MAC_get_TSU_oss_mode(const mss_mac_instance_t * this_mac)3663 mss_mac_oss_mode_t MSS_MAC_get_TSU_oss_mode(const mss_mac_instance_t *this_mac)
3664 {
3665     mss_mac_oss_mode_t ret_val = MSS_MAC_OSS_MODE_DISABLED;
3666     volatile uint32_t temp_control;
3667 
3668     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3669     {
3670         if(0U != this_mac->is_emac)
3671         {
3672             temp_control = this_mac->emac_base->NETWORK_CONTROL;
3673         }
3674         else
3675         {
3676             temp_control = this_mac->mac_base->NETWORK_CONTROL;
3677         }
3678 
3679         /*
3680          * Note. The docs don't say these are mutually exclusive but I don't think
3681          * it makes sense to allow both modes at once so report this as invalid...
3682          */
3683         if((GEM_OSS_CORRECTION_FIELD | GEM_ONE_STEP_SYNC_MODE) == (temp_control & (GEM_OSS_CORRECTION_FIELD | GEM_ONE_STEP_SYNC_MODE)))
3684         {
3685             ret_val = MSS_MAC_OSS_MODE_INVALID;
3686         }
3687         else if(GEM_OSS_CORRECTION_FIELD == (temp_control & GEM_OSS_CORRECTION_FIELD))
3688         {
3689             ret_val = MSS_MAC_OSS_MODE_ADJUST;
3690         }
3691         else if(GEM_ONE_STEP_SYNC_MODE == (temp_control & GEM_ONE_STEP_SYNC_MODE))
3692         {
3693             ret_val = MSS_MAC_OSS_MODE_REPLACE;
3694         }
3695         else
3696         {
3697             ret_val = MSS_MAC_OSS_MODE_DISABLED;
3698         }
3699     }
3700 
3701     return(ret_val);
3702 }
3703 
3704 
3705 /******************************************************************************
3706  * See mss_ethernet_mac.h for details of how to use this function.
3707  */
3708 
MSS_MAC_set_TSU_unicast_addr(const mss_mac_instance_t * this_mac,mss_mac_tsu_addr_t select,uint32_t ip_address)3709 void MSS_MAC_set_TSU_unicast_addr(const mss_mac_instance_t *this_mac, mss_mac_tsu_addr_t select, uint32_t ip_address)
3710 {
3711     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3712     {
3713         if(0U != this_mac->is_emac)
3714         {
3715             if(MSS_MAC_TSU_UNICAST_RX == select)
3716             {
3717                 this_mac->emac_base->RX_PTP_UNICAST = ip_address;
3718             }
3719             else
3720             {
3721                 this_mac->emac_base->TX_PTP_UNICAST = ip_address;
3722             }
3723         }
3724         else
3725         {
3726             if(MSS_MAC_TSU_UNICAST_RX == select)
3727             {
3728                 this_mac->mac_base->RX_PTP_UNICAST = ip_address;
3729             }
3730             else
3731             {
3732                 this_mac->mac_base->TX_PTP_UNICAST = ip_address;
3733             }
3734         }
3735     }
3736 }
3737 
3738 
3739 /******************************************************************************
3740  * See mss_ethernet_mac.h for details of how to use this function.
3741  */
3742 
MSS_MAC_get_TSU_unicast_addr(const mss_mac_instance_t * this_mac,mss_mac_tsu_addr_t select)3743 uint32_t MSS_MAC_get_TSU_unicast_addr(const mss_mac_instance_t *this_mac, mss_mac_tsu_addr_t select)
3744 {
3745     uint32_t ret_val = 0U;
3746 
3747     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3748     {
3749         if(0U != this_mac->is_emac)
3750         {
3751             if(MSS_MAC_TSU_UNICAST_RX == select)
3752             {
3753                 ret_val = this_mac->emac_base->RX_PTP_UNICAST;
3754             }
3755             else
3756             {
3757                 ret_val = this_mac->emac_base->TX_PTP_UNICAST;
3758             }
3759         }
3760         else
3761         {
3762             if(MSS_MAC_TSU_UNICAST_RX == select)
3763             {
3764                 ret_val = this_mac->mac_base->RX_PTP_UNICAST;
3765             }
3766             else
3767             {
3768                 ret_val = this_mac->mac_base->TX_PTP_UNICAST;
3769             }
3770         }
3771     }
3772 
3773     return(ret_val);
3774 }
3775 
3776 
3777 /******************************************************************************
3778  * See mss_ethernet_mac.h for details of how to use this function.
3779  */
3780 
MSS_MAC_set_VLAN_only_mode(const mss_mac_instance_t * this_mac,bool enable)3781 void MSS_MAC_set_VLAN_only_mode(const mss_mac_instance_t *this_mac, bool enable)
3782 {
3783     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3784     {
3785         if(0U != this_mac->is_emac)
3786         {
3787             if(false == enable)
3788             {
3789                 this_mac->emac_base->NETWORK_CONFIG &= ~GEM_DISCARD_NON_VLAN_FRAMES;
3790             }
3791             else
3792             {
3793                 this_mac->emac_base->NETWORK_CONFIG |= GEM_DISCARD_NON_VLAN_FRAMES;
3794             }
3795         }
3796         else
3797         {
3798             if(false == enable)
3799             {
3800                 this_mac->mac_base->NETWORK_CONFIG &= ~GEM_DISCARD_NON_VLAN_FRAMES;
3801             }
3802             else
3803             {
3804                 this_mac->mac_base->NETWORK_CONFIG |= GEM_DISCARD_NON_VLAN_FRAMES;
3805             }
3806         }
3807     }
3808 }
3809 
3810 
3811 /******************************************************************************
3812  * See mss_ethernet_mac.h for details of how to use this function.
3813  */
3814 
MSS_MAC_get_VLAN_only_mode(const mss_mac_instance_t * this_mac)3815 bool MSS_MAC_get_VLAN_only_mode(const mss_mac_instance_t *this_mac)
3816 {
3817     bool ret_val = false;
3818 
3819     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3820     {
3821         if(0U != this_mac->is_emac)
3822         {
3823             ret_val = 0U != (this_mac->emac_base->NETWORK_CONFIG & GEM_DISCARD_NON_VLAN_FRAMES);
3824         }
3825         else
3826         {
3827             ret_val = 0U != (this_mac->mac_base->NETWORK_CONFIG & GEM_DISCARD_NON_VLAN_FRAMES);
3828         }
3829     }
3830 
3831     return(ret_val);
3832 }
3833 
3834 
3835 /******************************************************************************
3836  * See mss_ethernet_mac.h for details of how to use this function.
3837  */
3838 
MSS_MAC_set_stacked_VLAN(const mss_mac_instance_t * this_mac,uint16_t tag)3839 void MSS_MAC_set_stacked_VLAN(const mss_mac_instance_t *this_mac, uint16_t tag)
3840 {
3841     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3842     {
3843         if(0U != this_mac->is_emac)
3844         {
3845             if(GEM_VLAN_ETHERTYPE_MIN > tag)
3846             {
3847                 this_mac->emac_base->STACKED_VLAN = 0U;
3848             }
3849             else
3850             {
3851                 this_mac->emac_base->STACKED_VLAN = (uint32_t)tag | GEM_ENABLE_PROCESSING;
3852             }
3853         }
3854         else
3855         {
3856             if(GEM_VLAN_ETHERTYPE_MIN > tag)
3857             {
3858                 this_mac->mac_base->STACKED_VLAN = 0U;
3859             }
3860             else
3861             {
3862                 this_mac->mac_base->STACKED_VLAN = (uint32_t)tag | GEM_ENABLE_PROCESSING;
3863             }
3864         }
3865     }
3866 }
3867 
3868 
3869 /******************************************************************************
3870  * See mss_ethernet_mac.h for details of how to use this function.
3871  */
3872 
MSS_MAC_get_stacked_VLAN(const mss_mac_instance_t * this_mac)3873 uint16_t MSS_MAC_get_stacked_VLAN(const mss_mac_instance_t *this_mac)
3874 {
3875     uint16_t ret_val = GEM_VLAN_NO_STACK; /* Return 0 if stacked VLANs not enabled */
3876 
3877     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3878     {
3879         if(0U != this_mac->is_emac)
3880         {
3881             if(0U != (this_mac->emac_base->STACKED_VLAN & GEM_ENABLE_PROCESSING))
3882             {
3883                 ret_val = (uint16_t)this_mac->emac_base->STACKED_VLAN;
3884             }
3885         }
3886         else
3887         {
3888             if(0U != (this_mac->mac_base->STACKED_VLAN & GEM_ENABLE_PROCESSING))
3889             {
3890                 ret_val = (uint16_t)this_mac->mac_base->STACKED_VLAN;
3891             }
3892         }
3893     }
3894 
3895     return(ret_val);
3896 }
3897 
3898 
3899 /******************************************************************************
3900  * See mss_ethernet_mac.h for details of how to use this function.
3901  */
3902 
MSS_MAC_set_hash(const mss_mac_instance_t * this_mac,uint64_t hash_in)3903 void MSS_MAC_set_hash(const mss_mac_instance_t *this_mac, uint64_t hash_in)
3904 {
3905     uint64_t hash = hash_in; /* Avoids warning about modifying fn parameter passed by value */
3906 
3907     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3908     {
3909         if(0U != this_mac->is_emac)
3910         {
3911             if(0ULL == hash) /* Short cut for disabling */
3912             {
3913                 this_mac->emac_base->NETWORK_CONFIG &= ~(GEM_UNICAST_HASH_ENABLE | GEM_MULTICAST_HASH_ENABLE);
3914             }
3915 
3916             this_mac->emac_base->HASH_BOTTOM = (uint32_t)hash;
3917             hash >>= 32;
3918             this_mac->emac_base->HASH_TOP = (uint32_t)hash;
3919         }
3920         else
3921         {
3922             if(0ULL == hash) /* Short cut for disabling */
3923             {
3924                 this_mac->mac_base->NETWORK_CONFIG &= ~(GEM_UNICAST_HASH_ENABLE | GEM_MULTICAST_HASH_ENABLE);
3925             }
3926 
3927             this_mac->mac_base->HASH_BOTTOM = (uint32_t)hash;
3928             hash >>= 32;
3929             this_mac->mac_base->HASH_TOP = (uint32_t)hash;
3930         }
3931     }
3932 }
3933 
3934 
3935 /******************************************************************************
3936  * See mss_ethernet_mac.h for details of how to use this function.
3937  */
3938 
MSS_MAC_get_hash(const mss_mac_instance_t * this_mac)3939 uint64_t MSS_MAC_get_hash(const mss_mac_instance_t *this_mac)
3940 {
3941     uint64_t ret_val = 0U;
3942 
3943     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3944     {
3945         if(0U != this_mac->is_emac)
3946         {
3947             ret_val   = (uint64_t)this_mac->emac_base->HASH_TOP;
3948             ret_val <<= 32;
3949             ret_val  |= (uint64_t)this_mac->emac_base->HASH_BOTTOM;
3950         }
3951         else
3952         {
3953             ret_val   = (uint64_t)this_mac->mac_base->HASH_TOP;
3954             ret_val <<= 32;
3955             ret_val  |= (uint64_t)this_mac->mac_base->HASH_BOTTOM;
3956         }
3957     }
3958 
3959     return(ret_val);
3960 }
3961 
3962 
3963 /******************************************************************************
3964  * See mss_ethernet_mac.h for details of how to use this function.
3965  */
3966 
MSS_MAC_set_hash_mode(const mss_mac_instance_t * this_mac,mss_mac_hash_mode_t mode)3967 void MSS_MAC_set_hash_mode(const mss_mac_instance_t *this_mac, mss_mac_hash_mode_t mode)
3968 {
3969     uint32_t temp;
3970 
3971     /*
3972      * Enum values are matched to register bits but just to be safe we mask them
3973      * to ensure only the two hash control bits are modified...
3974      */
3975     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
3976     {
3977         if(0U != this_mac->is_emac)
3978         {
3979             temp = this_mac->emac_base->NETWORK_CONFIG & ~(GEM_UNICAST_HASH_ENABLE | GEM_MULTICAST_HASH_ENABLE);
3980             temp |= (uint32_t)mode & (GEM_UNICAST_HASH_ENABLE | GEM_MULTICAST_HASH_ENABLE);
3981             this_mac->emac_base->NETWORK_CONFIG = temp;
3982         }
3983         else
3984         {
3985             temp = this_mac->mac_base->NETWORK_CONFIG & ~(GEM_UNICAST_HASH_ENABLE | GEM_MULTICAST_HASH_ENABLE);
3986             temp |= (uint32_t)mode & (GEM_UNICAST_HASH_ENABLE | GEM_MULTICAST_HASH_ENABLE);
3987             this_mac->mac_base->NETWORK_CONFIG = temp;
3988         }
3989     }
3990 }
3991 
3992 
3993 /******************************************************************************
3994  * See mss_ethernet_mac.h for details of how to use this function.
3995  */
3996 
MSS_MAC_get_hash_mode(const mss_mac_instance_t * this_mac)3997 mss_mac_hash_mode_t MSS_MAC_get_hash_mode(const mss_mac_instance_t *this_mac)
3998 {
3999     mss_mac_hash_mode_t ret_val = 0;
4000 
4001     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4002     {
4003         if(0U != this_mac->is_emac)
4004         {
4005             ret_val = (mss_mac_hash_mode_t)(this_mac->emac_base->NETWORK_CONFIG & (GEM_UNICAST_HASH_ENABLE | GEM_MULTICAST_HASH_ENABLE));
4006         }
4007         else
4008         {
4009             ret_val = (mss_mac_hash_mode_t)(this_mac->mac_base->NETWORK_CONFIG & (GEM_UNICAST_HASH_ENABLE | GEM_MULTICAST_HASH_ENABLE));
4010         }
4011     }
4012 
4013     return(ret_val);
4014 }
4015 
4016 
4017 /******************************************************************************
4018  * See mss_ethernet_mac.h for details of how to use this function.
4019  */
4020 
MSS_MAC_set_type_filter(const mss_mac_instance_t * this_mac,uint32_t filter,uint16_t value)4021 void MSS_MAC_set_type_filter(const mss_mac_instance_t *this_mac, uint32_t filter, uint16_t value)
4022 {
4023     volatile uint32_t *p_reg;
4024 
4025     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4026     {
4027         if(0U != this_mac->is_emac)
4028         {
4029             p_reg = &this_mac->emac_base->SPEC_TYPE1;
4030         }
4031         else
4032         {
4033             p_reg = &this_mac->mac_base->SPEC_TYPE1;
4034         }
4035         if((filter <= 4U) && (filter > 0U)) /* Filter is in range 1 to 4 to match register naming */
4036         {
4037             p_reg += filter - 1U;
4038             if(0U == value) /* Disable filter if match value is 0 as this should not be a valid type */
4039             {
4040                 *p_reg = 0U;
4041             }
4042             else
4043             {
4044                 *p_reg = (uint32_t)(0x80000000UL | (uint32_t)value);
4045             }
4046         }
4047     }
4048 }
4049 
4050 
4051 /******************************************************************************
4052  * See mss_ethernet_mac.h for details of how to use this function.
4053  */
4054 
MSS_MAC_get_type_filter(const mss_mac_instance_t * this_mac,uint32_t filter)4055 uint16_t MSS_MAC_get_type_filter(const mss_mac_instance_t *this_mac, uint32_t filter)
4056 {
4057     volatile uint32_t *p_reg;
4058     uint16_t ret_val = 0U;
4059 
4060     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4061     {
4062         if(0U != this_mac->is_emac)
4063         {
4064             p_reg = &this_mac->emac_base->SPEC_TYPE1;
4065         }
4066         else
4067         {
4068             p_reg = &this_mac->mac_base->SPEC_TYPE1;
4069         }
4070 
4071         if((filter <= 4U) && (filter > 0U)) /* Filter is in range 1 to 4 to match register naming */
4072         {
4073             p_reg += filter - 1U;
4074             if(0U != (*p_reg & 0x80000000UL)) /* Not disabled filter... */
4075             {
4076                 ret_val = (uint16_t)*p_reg;
4077             }
4078         }
4079     }
4080 
4081     return(ret_val);
4082 }
4083 
4084 
4085 /******************************************************************************
4086  * See mss_ethernet_mac.h for details of how to use this function.
4087  */
4088 
MSS_MAC_set_sa_filter(const mss_mac_instance_t * this_mac,uint32_t filter,uint16_t control,const uint8_t * mac_addr)4089 void MSS_MAC_set_sa_filter(const mss_mac_instance_t *this_mac, uint32_t filter, uint16_t control, const uint8_t *mac_addr)
4090 {
4091     volatile uint32_t *p_reg;
4092     uint32_t address32_l;
4093     uint32_t address32_h;
4094 
4095     ASSERT(NULL_POINTER!= mac_addr);
4096 
4097     if((MSS_MAC_AVAILABLE == this_mac->mac_available) && (NULL_POINTER != mac_addr))
4098     {
4099         if((filter >= 2U) && (filter <= 4U)) /* SA Filter 1 is for our address */
4100         {
4101             if(0U != this_mac->is_emac)
4102             {
4103                 p_reg = &this_mac->emac_base->SPEC_ADD2_BOTTOM;
4104             }
4105             else
4106             {
4107                 p_reg = &this_mac->mac_base->SPEC_ADD2_BOTTOM;
4108             }
4109 
4110             p_reg = p_reg + ((filter - 2U) * 2U);
4111 
4112             if(MSS_MAC_SA_FILTER_DISABLE == control)
4113             {
4114                 /*
4115                  * Clear filter and disable - must be done in this order...
4116                  *  Writing to [0] disables and [1] enables So this sequence
4117                  *  clears the registers and disables the filter as opposed to
4118                  *  setting a destination address filter for 00:00:00:00:00:00.
4119                  */
4120                 p_reg[1] = 0U;
4121                 p_reg[0] = 0U;
4122             }
4123             else
4124             {
4125                 /* Assemble correct register values */
4126                 address32_l  = ((uint32_t)mac_addr[3]) << 24;
4127                 address32_l |= ((uint32_t)mac_addr[2]) << 16;
4128                 address32_l |= ((uint32_t)mac_addr[1]) << 8;
4129                 address32_l |= ((uint32_t)mac_addr[0]);
4130                 address32_h =  ((uint32_t)mac_addr[5]) << 8;
4131                 address32_h |= ((uint32_t)mac_addr[4]);
4132 
4133                 address32_h |= (uint32_t)control << 16;
4134 
4135                 /* Update hardware registers - must be done in this order... */
4136                 p_reg[0] = address32_l;
4137                 p_reg[1] = address32_h;
4138             }
4139         }
4140     }
4141 }
4142 
4143 
4144 /******************************************************************************
4145  * See mss_ethernet_mac.h for details of how to use this function.
4146  */
4147 
MSS_MAC_get_sa_filter(const mss_mac_instance_t * this_mac,uint32_t filter,uint8_t * mac_addr)4148 uint16_t MSS_MAC_get_sa_filter(const mss_mac_instance_t *this_mac, uint32_t filter, uint8_t *mac_addr)
4149 {
4150     volatile uint32_t *p_reg;
4151     uint32_t temp_reg;
4152     uint16_t ret_val = 0U;
4153 
4154     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4155     {
4156         if(NULL_POINTER != mac_addr)
4157         {
4158             (void)memset(mac_addr, 0, 6); /* Consistent result if bad parameters passed... */
4159         }
4160 
4161         if((filter >= 2U) && (filter <= 4U))
4162         {
4163             if(0U != this_mac->is_emac)
4164             {
4165                 p_reg = &this_mac->emac_base->SPEC_ADD2_BOTTOM;
4166             }
4167             else
4168             {
4169                 p_reg = &this_mac->mac_base->SPEC_ADD2_BOTTOM;
4170             }
4171 
4172             p_reg = p_reg + ((filter - 2U) * 2U);
4173 
4174             if(NULL_POINTER != mac_addr) /* Want MAC address and filter control info? */
4175             {
4176                 temp_reg = p_reg[0];
4177                 mac_addr[0] = (uint8_t)temp_reg & BITS_08;
4178                 temp_reg >>= 8;
4179                 mac_addr[1] = (uint8_t)temp_reg & BITS_08;
4180                 temp_reg >>= 8;
4181                 mac_addr[2] = (uint8_t)temp_reg & BITS_08;
4182                 temp_reg >>= 8;
4183                 mac_addr[3] = (uint8_t)temp_reg & BITS_08;
4184 
4185                 temp_reg = p_reg[1];
4186                 mac_addr[4] = (uint8_t)temp_reg & BITS_08;
4187                 temp_reg >>= 8;
4188                 mac_addr[5] = (uint8_t)temp_reg & BITS_08;
4189             }
4190 
4191             ret_val = (uint16_t)(p_reg[1] >> 16);
4192         }
4193     }
4194 
4195     return(ret_val);
4196 }
4197 
4198 
4199 /******************************************************************************
4200  * See mss_ethernet_mac.h for details of how to use this function.
4201  */
4202 
MSS_MAC_set_type_1_filter(const mss_mac_instance_t * this_mac,uint32_t filter_no,const mss_mac_type_1_filter_t * filter)4203 void MSS_MAC_set_type_1_filter(const mss_mac_instance_t *this_mac, uint32_t filter_no, const mss_mac_type_1_filter_t *filter)
4204 {
4205     if((MSS_MAC_AVAILABLE == this_mac->mac_available) && (filter_no < MSS_MAC_TYPE_1_SCREENERS))
4206     {
4207         volatile uint32_t *p_reg;
4208         uint32_t temp_reg;
4209 
4210         if(0U != this_mac->is_emac)
4211         {
4212             p_reg = &this_mac->emac_base->SCREENING_TYPE_1_REGISTER_0;
4213         }
4214         else
4215         {
4216             p_reg = &this_mac->mac_base->SCREENING_TYPE_1_REGISTER_0;
4217         }
4218 
4219         temp_reg  = (uint32_t)filter->queue_no & GEM_QUEUE_NUMBER;
4220         temp_reg |= ((uint32_t)filter->dstc << GEM_DSTC_MATCH_SHIFT) & GEM_DSTC_MATCH;
4221         temp_reg |= ((uint32_t)filter->udp_port << GEM_UDP_PORT_MATCH_SHIFT) & GEM_UDP_PORT_MATCH;
4222         if(0U != filter->drop_on_match)
4223         {
4224             temp_reg |= GEM_DROP_ON_MATCH;
4225         }
4226 
4227         if(0U != filter->dstc_enable)
4228         {
4229             temp_reg |= GEM_DSTC_ENABLE;
4230         }
4231 
4232         if(0U != filter->udp_port_enable)
4233         {
4234             temp_reg |= GEM_UDP_PORT_MATCH_ENABLE;
4235         }
4236 
4237         p_reg[filter_no] = temp_reg;
4238     }
4239 }
4240 
4241 
4242 /******************************************************************************
4243  * See mss_ethernet_mac.h for details of how to use this function.
4244  */
4245 
MSS_MAC_get_type_1_filter(const mss_mac_instance_t * this_mac,uint32_t filter_no,mss_mac_type_1_filter_t * filter)4246 void MSS_MAC_get_type_1_filter(const mss_mac_instance_t *this_mac, uint32_t filter_no, mss_mac_type_1_filter_t *filter)
4247 {
4248 
4249     if((MSS_MAC_AVAILABLE == this_mac->mac_available) && (filter_no < MSS_MAC_TYPE_1_SCREENERS))
4250     {
4251         volatile uint32_t *p_reg;
4252         uint32_t temp_reg;
4253 
4254         (void)memset(filter, 0, sizeof(mss_mac_type_1_filter_t)); /* Blank canvass to start */
4255 
4256         if(0U != this_mac->is_emac)
4257         {
4258             p_reg = &this_mac->emac_base->SCREENING_TYPE_1_REGISTER_0;
4259         }
4260         else
4261         {
4262             p_reg = &this_mac->mac_base->SCREENING_TYPE_1_REGISTER_0;
4263         }
4264 
4265         temp_reg = p_reg[filter_no];
4266 
4267         filter->queue_no = (uint8_t)(temp_reg & GEM_QUEUE_NUMBER);
4268         temp_reg >>= 4;
4269 
4270         filter->dstc = (uint8_t)(temp_reg & GEM_DSTC_MATCH);
4271         temp_reg >>= GEM_DSTC_MATCH_SHIFT;
4272 
4273         filter->udp_port = (uint16_t)(temp_reg & GEM_UDP_PORT_MATCH);
4274         temp_reg >>= GEM_UDP_PORT_MATCH_SHIFT;
4275 
4276         filter->dstc_enable = (uint8_t)(temp_reg & 1U);
4277         temp_reg >>= 1;
4278 
4279         filter->udp_port_enable = (uint8_t)(temp_reg & 1U);
4280         temp_reg >>= 1;
4281 
4282         filter->drop_on_match = (uint8_t)(temp_reg & 1U);
4283     }
4284 }
4285 
4286 
4287 /******************************************************************************
4288  * See mss_ethernet_mac.h for details of how to use this function.
4289  */
4290 
MSS_MAC_set_type_2_ethertype(const mss_mac_instance_t * this_mac,uint32_t ethertype_no,uint16_t ethertype)4291 void MSS_MAC_set_type_2_ethertype(const mss_mac_instance_t *this_mac, uint32_t ethertype_no, uint16_t ethertype)
4292 {
4293     volatile uint32_t *p_reg;
4294 
4295     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4296     {
4297         if(0U == this_mac->is_emac) /* Ethertype filter not supported on eMAC */
4298         {
4299             p_reg = &this_mac->mac_base->SCREENING_TYPE_2_ETHERTYPE_REG_0;
4300             if(ethertype_no < MSS_MAC_TYPE_2_ETHERTYPES)
4301             {
4302                 p_reg[ethertype_no] = (uint32_t)ethertype;
4303             }
4304         }
4305     }
4306 }
4307 
4308 
4309 /******************************************************************************
4310  * See mss_ethernet_mac.h for details of how to use this function.
4311  */
4312 
MSS_MAC_get_type_2_ethertype(const mss_mac_instance_t * this_mac,uint32_t ethertype_no)4313 uint16_t MSS_MAC_get_type_2_ethertype(const mss_mac_instance_t *this_mac, uint32_t ethertype_no)
4314 {
4315     volatile uint32_t *p_reg;
4316     uint16_t temp_reg = 0U;
4317 
4318     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4319     {
4320         if(0U == this_mac->is_emac) /* Ethertype filter not supported on eMAC */
4321         {
4322             p_reg = &this_mac->mac_base->SCREENING_TYPE_2_ETHERTYPE_REG_0;
4323             if(ethertype_no < MSS_MAC_TYPE_2_ETHERTYPES)
4324             {
4325                 temp_reg = (uint16_t)p_reg[ethertype_no];
4326             }
4327         }
4328     }
4329 
4330     return(temp_reg);
4331 }
4332 
4333 
4334 /******************************************************************************
4335  * See mss_ethernet_mac.h for details of how to use this function.
4336  */
4337 
MSS_MAC_set_type_2_compare(const mss_mac_instance_t * this_mac,uint32_t comparer_no_in,const mss_mac_type_2_compare_t * comparer)4338 void MSS_MAC_set_type_2_compare(const mss_mac_instance_t *this_mac, uint32_t comparer_no_in, const mss_mac_type_2_compare_t *comparer)
4339 {
4340     volatile uint32_t *p_reg;
4341     uint32_t limit;
4342     uint32_t temp_reg;
4343     uint32_t comparer_no = comparer_no_in;
4344 
4345     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4346     {
4347         if(0U != this_mac->is_emac) /* eMAC limits are different to pMAC ones */
4348         {
4349             p_reg = &this_mac->emac_base->TYPE2_COMPARE_0_WORD_0;
4350             limit = MSS_MAC_EMAC_TYPE_2_COMPARERS;
4351         }
4352         else
4353         {
4354             p_reg = &this_mac->mac_base->TYPE2_COMPARE_0_WORD_0;
4355             limit = MSS_MAC_TYPE_2_COMPARERS;
4356         }
4357 
4358         if(comparer_no < limit)
4359         {
4360             comparer_no *= 2U; /* Working with consecutive pairs of registers for this one */
4361             if(0U != comparer->disable_mask)
4362             {
4363                 p_reg[comparer_no] = comparer->data; /* Mask disabled so just 4 byte compare value */
4364                 temp_reg = GEM_DISABLE_MASK;         /* and no mask */
4365             }
4366             else
4367             {
4368                 temp_reg  = comparer->data << 16;     /* 16 bit compare value and 16 bit mask */
4369                 temp_reg |= (uint32_t)comparer->mask;
4370                 p_reg[comparer_no] = temp_reg;
4371                 temp_reg = 0U;
4372             }
4373 
4374             if(0U != comparer->compare_vlan_c_id)
4375             {
4376                 temp_reg |= GEM_COMPARE_VLAN_ID;
4377             }
4378             else if(0U != comparer->compare_vlan_s_id)
4379             {
4380                 temp_reg |= GEM_COMPARE_VLAN_ID | GEM_COMPARE_S_TAG;
4381             }
4382             else
4383             {
4384                 temp_reg |= (uint32_t)comparer->offset_value & BITS_07;
4385                 temp_reg |= ((uint32_t)comparer->compare_offset & BITS_02) << GEM_COMPARE_OFFSET_SHIFT;
4386             }
4387 
4388             p_reg[comparer_no + 1] = temp_reg; /* Set second word of comparer */
4389         }
4390     }
4391 }
4392 
4393 
4394 /******************************************************************************
4395  * See mss_ethernet_mac.h for details of how to use this function.
4396  */
4397 
MSS_MAC_get_type_2_compare(const mss_mac_instance_t * this_mac,uint32_t comparer_no_in,mss_mac_type_2_compare_t * comparer)4398 void MSS_MAC_get_type_2_compare(const mss_mac_instance_t *this_mac, uint32_t comparer_no_in, mss_mac_type_2_compare_t *comparer)
4399 {
4400     volatile uint32_t *p_reg;
4401     uint32_t limit;
4402     uint32_t comparer_no = comparer_no_in;
4403 
4404     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4405     {
4406         if(0U != this_mac->is_emac) /* eMAC limits are different to pMAC ones */
4407         {
4408             p_reg = &this_mac->emac_base->TYPE2_COMPARE_0_WORD_0;
4409             limit = MSS_MAC_EMAC_TYPE_2_COMPARERS;
4410         }
4411         else
4412         {
4413             p_reg = &this_mac->mac_base->TYPE2_COMPARE_0_WORD_0;
4414             limit = MSS_MAC_TYPE_2_COMPARERS;
4415         }
4416 
4417         (void)memset(comparer, 0, sizeof(mss_mac_type_2_compare_t));
4418         if(comparer_no < limit)
4419         {
4420             comparer_no *= 2U; /* Working with consecutive pairs of registers for this one */
4421             if(0U != (p_reg[comparer_no + 1] & GEM_DISABLE_MASK))
4422             {
4423                 comparer->data = p_reg[comparer_no]; /* Mask disabled so just 4 byte compare value */
4424                 comparer->disable_mask = 1;          /* and no mask */
4425             }
4426             else
4427             {
4428                 comparer->data = p_reg[comparer_no] >> 16;     /* 16 bit compare value and 16 bit mask */
4429                 comparer->mask = (uint16_t)p_reg[comparer_no];
4430             }
4431 
4432             if(0U != (p_reg[comparer_no + 1U] & GEM_COMPARE_VLAN_ID))
4433             {
4434                 if(0U != (p_reg[comparer_no + 1U] & GEM_COMPARE_S_TAG))
4435                 {
4436                     comparer->compare_vlan_s_id = 1U;
4437                 }
4438                 else
4439                 {
4440                     comparer->compare_vlan_c_id = 1U;
4441                 }
4442             }
4443             else
4444             {
4445                 comparer->compare_offset = (uint8_t)((p_reg[comparer_no + 1U] >> GEM_COMPARE_OFFSET_SHIFT) & BITS_02);
4446             }
4447 
4448             comparer->offset_value = (uint8_t)(p_reg[comparer_no + 1U] & GEM_OFFSET_VALUE);
4449         }
4450     }
4451 }
4452 
4453 
4454 /******************************************************************************
4455  * See mss_ethernet_mac.h for details of how to use this function.
4456  */
4457 
MSS_MAC_set_type_2_filter(const mss_mac_instance_t * this_mac,uint32_t filter_no,const mss_mac_type_2_filter_t * filter)4458 void MSS_MAC_set_type_2_filter(const mss_mac_instance_t *this_mac, uint32_t filter_no, const mss_mac_type_2_filter_t *filter)
4459 {
4460     volatile uint32_t *p_reg;
4461     uint32_t limit;
4462     uint32_t temp_reg = 0U;
4463 
4464     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4465     {
4466         if(0U != this_mac->is_emac) /* eMAC limits are different to pMAC ones */
4467         {
4468             p_reg = &this_mac->emac_base->SCREENING_TYPE_2_REGISTER_0;
4469             limit = MSS_MAC_EMAC_TYPE_2_SCREENERS;
4470         }
4471         else
4472         {
4473             p_reg = &this_mac->mac_base->SCREENING_TYPE_2_REGISTER_0;
4474             limit = MSS_MAC_TYPE_2_SCREENERS;
4475         }
4476 
4477         if(filter_no < limit) /* Lets go build a filter... */
4478         {
4479             if(0u != (filter->drop_on_match))
4480             {
4481                 temp_reg = GEM_T2_DROP_ON_MATCH;
4482             }
4483             else
4484             {
4485                 temp_reg = 0U;
4486             }
4487 
4488             if(0U != (filter->compare_a_enable))
4489             {
4490                 temp_reg |= GEM_COMPARE_A_ENABLE;
4491                 temp_reg |= ((uint32_t)filter->compare_a_index & BITS_05) << GEM_COMPARE_A_SHIFT;
4492             }
4493 
4494             if(0U != (filter->compare_b_enable))
4495             {
4496                 temp_reg |= GEM_COMPARE_B_ENABLE;
4497                 temp_reg |= ((uint32_t)filter->compare_b_index & BITS_05) << GEM_COMPARE_B_SHIFT;
4498             }
4499 
4500             if(0U != (filter->compare_c_enable))
4501             {
4502                 temp_reg |= GEM_COMPARE_C_ENABLE;
4503                 temp_reg |= ((uint32_t)filter->compare_c_index & BITS_05) << GEM_COMPARE_C_SHIFT;
4504             }
4505 
4506             if(0U != (filter->ethertype_enable))
4507             {
4508                 temp_reg |= GEM_ETHERTYPE_ENABLE;
4509                 temp_reg |= ((uint32_t)filter->ethertype_index & BITS_03) << GEM_ETHERTYPE_REG_INDEX_SHIFT;
4510             }
4511 
4512             if(0U != (filter->vlan_priority_enable))
4513             {
4514                 temp_reg |= GEM_VLAN_ENABLE;
4515                 temp_reg |= ((uint32_t)filter->vlan_priority & BITS_03) << GEM_VLAN_PRIORITY_SHIFT;
4516             }
4517 
4518             temp_reg |= (uint32_t)filter->queue_no & GEM_QUEUE_NUMBER;
4519 
4520             p_reg[filter_no] = temp_reg; /* Set filter up at last */
4521         }
4522     }
4523 }
4524 
4525 
4526 /******************************************************************************
4527  * See mss_ethernet_mac.h for details of how to use this function.
4528  */
4529 
MSS_MAC_get_type_2_filter(const mss_mac_instance_t * this_mac,uint32_t filter_no,mss_mac_type_2_filter_t * filter)4530 void MSS_MAC_get_type_2_filter(const mss_mac_instance_t *this_mac, uint32_t filter_no, mss_mac_type_2_filter_t *filter)
4531 {
4532     volatile uint32_t *p_reg;
4533     uint32_t limit;
4534 
4535     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4536     {
4537         (void)memset(filter, 0, sizeof(mss_mac_type_2_filter_t));
4538         if(0U != this_mac->is_emac) /* eMAC limits are different to pMAC ones */
4539         {
4540             p_reg = &this_mac->emac_base->SCREENING_TYPE_2_REGISTER_0;
4541             limit = MSS_MAC_EMAC_TYPE_2_SCREENERS;
4542         }
4543         else
4544         {
4545             p_reg = &this_mac->mac_base->SCREENING_TYPE_2_REGISTER_0;
4546             limit = MSS_MAC_TYPE_2_SCREENERS;
4547         }
4548 
4549         if(filter_no < limit) /* Lets go fetch a filter... */
4550         {
4551             if(0U != (p_reg[filter_no] & GEM_T2_DROP_ON_MATCH))
4552             {
4553                 filter->drop_on_match = 1;
4554             }
4555 
4556             if(0U != (p_reg[filter_no] & GEM_COMPARE_A_ENABLE))
4557             {
4558                 filter->compare_a_enable = 1;
4559             }
4560 
4561             if(0U != (p_reg[filter_no] & GEM_COMPARE_B_ENABLE))
4562             {
4563                 filter->compare_b_enable = 1;
4564             }
4565 
4566             if(0U != (p_reg[filter_no] & GEM_COMPARE_C_ENABLE))
4567             {
4568                 filter->compare_c_enable = 1;
4569             }
4570 
4571             if(0U != (p_reg[filter_no] & GEM_ETHERTYPE_ENABLE))
4572             {
4573                 filter->ethertype_enable = 1;
4574             }
4575 
4576             if(0U != (p_reg[filter_no] & GEM_VLAN_ENABLE))
4577             {
4578                 filter->vlan_priority_enable = 1;
4579             }
4580 
4581             filter->compare_a_index = (uint8_t)((p_reg[filter_no] & GEM_COMPARE_A) >> GEM_COMPARE_A_SHIFT);
4582             filter->compare_b_index = (uint8_t)((p_reg[filter_no] & GEM_COMPARE_B) >> GEM_COMPARE_B_SHIFT);
4583             filter->compare_c_index = (uint8_t)((p_reg[filter_no] & GEM_COMPARE_C) >> GEM_COMPARE_C_SHIFT);
4584             filter->ethertype_index = (uint8_t)((p_reg[filter_no] & GEM_ETHERTYPE_REG_INDEX) >> GEM_ETHERTYPE_REG_INDEX_SHIFT);
4585             filter->vlan_priority   = (uint8_t)((p_reg[filter_no] & GEM_VLAN_PRIORITY) >> GEM_VLAN_PRIORITY_SHIFT);
4586             filter->queue_no        = (uint8_t)(p_reg[filter_no] & GEM_QUEUE_NUMBER);
4587         }
4588     }
4589 }
4590 
4591 
4592 /******************************************************************************
4593  * See mss_ethernet_mac.h for details of how to use this function.
4594  */
4595 
MSS_MAC_set_mmsl_mode(const mss_mac_instance_t * this_mac,const mss_mac_mmsl_config_t * mmsl_cfg)4596 void MSS_MAC_set_mmsl_mode(const mss_mac_instance_t *this_mac, const mss_mac_mmsl_config_t *mmsl_cfg)
4597 {
4598     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4599     {
4600         if(0U != mmsl_cfg->preemption) /* Preemption is enabled so deal with it */
4601         {
4602             /*
4603              * Need to shut preemption down in case it is already enabled
4604              * otherwise the new settings may not be recognised properly.
4605              */
4606             this_mac->mac_base->MMSL_CONTROL = 0U;
4607 
4608             if(0U != mmsl_cfg->verify_disable)
4609             {
4610                 this_mac->mac_base->MMSL_CONTROL |= ((uint32_t)(mmsl_cfg->frag_size)) | GEM_VERIFY_DISABLE;
4611                 this_mac->mac_base->MMSL_CONTROL |= GEM_PRE_ENABLE;
4612             }
4613             else
4614             {
4615                 this_mac->mac_base->MMSL_CONTROL |= (uint32_t)(mmsl_cfg->frag_size);
4616                 this_mac->mac_base->MMSL_CONTROL |= GEM_PRE_ENABLE;
4617             }
4618         }
4619         else /* Preemption is not enabled so see which MAC we want to use */
4620         {
4621             if(0U != mmsl_cfg->use_pmac)
4622             {
4623                 this_mac->mac_base->MMSL_CONTROL = GEM_ROUTE_RX_TO_PMAC;
4624             }
4625             else
4626             {
4627                 this_mac->mac_base->MMSL_CONTROL = 0U;
4628             }
4629         }
4630     }
4631 }
4632 
4633 
4634 /******************************************************************************
4635  * See mss_ethernet_mac.h for details of how to use this function.
4636  */
4637 
MSS_MAC_get_mmsl_mode(const mss_mac_instance_t * this_mac,mss_mac_mmsl_config_t * mmsl_cfg)4638 void MSS_MAC_get_mmsl_mode(const mss_mac_instance_t *this_mac, mss_mac_mmsl_config_t *mmsl_cfg)
4639 {
4640     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4641     {
4642         (void)memset(mmsl_cfg, 0, sizeof(mss_mac_mmsl_config_t));
4643         if(0U != (this_mac->mac_base->MMSL_CONTROL & GEM_ROUTE_RX_TO_PMAC))
4644         {
4645             mmsl_cfg->use_pmac = 1U;
4646         }
4647 
4648         if(0U != (this_mac->mac_base->MMSL_CONTROL & GEM_PRE_ENABLE))
4649         {
4650             mmsl_cfg->preemption = 1U;
4651         }
4652 
4653         if(0U != (this_mac->mac_base->MMSL_CONTROL & GEM_VERIFY_DISABLE))
4654         {
4655             mmsl_cfg->verify_disable = 1U;
4656         }
4657 
4658         mmsl_cfg->frag_size = (mss_mac_frag_size_t)(this_mac->mac_base->MMSL_CONTROL & BITS_02);
4659     }
4660 }
4661 
4662 
4663 /******************************************************************************
4664  * See mss_ethernet_mac.h for details of how to use this function.
4665  */
4666 
MSS_MAC_start_preemption_verify(const mss_mac_instance_t * this_mac)4667 void MSS_MAC_start_preemption_verify(const mss_mac_instance_t *this_mac)
4668 {
4669     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4670     {
4671         if(0U != (this_mac->mac_base->MMSL_CONTROL & GEM_PRE_ENABLE)) /* Preemption is enabled */
4672         {
4673             this_mac->mac_base->MMSL_CONTROL |= GEM_RESTART_VER;
4674         }
4675     }
4676 }
4677 
4678 
4679 /******************************************************************************
4680  * See mss_ethernet_mac.h for details of how to use this function.
4681  */
4682 
MSS_MAC_get_mmsl_status(const mss_mac_instance_t * this_mac)4683 uint32_t MSS_MAC_get_mmsl_status(const mss_mac_instance_t *this_mac)
4684 {
4685     uint32_t ret_val = 0U;
4686 
4687     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4688     {
4689         ret_val = this_mac->mac_base->MMSL_STATUS; /* Just return raw value, user can decode using defined bits */
4690     }
4691 
4692     return(ret_val);
4693 }
4694 
4695 
4696 /******************************************************************************
4697  * See mss_ethernet_mac.h for details of how to use this function.
4698  */
4699 
MSS_MAC_get_mmsl_stats(const mss_mac_instance_t * this_mac,mss_mac_mmsl_stats_t * stats)4700 void MSS_MAC_get_mmsl_stats(const mss_mac_instance_t *this_mac, mss_mac_mmsl_stats_t *stats)
4701 {
4702     /*
4703      * We return these differently to the general statistics as they are pMAC
4704      * specific and don't have a corresponding eMAC equivalent.
4705      */
4706     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4707     {
4708         (void)memset(stats, 0, sizeof(mss_mac_mmsl_stats_t));
4709         stats->smd_err_count = (this_mac->mac_base->MMSL_ERR_STATS & GEM_SMD_ERR_COUNT) >> GEM_SMD_ERR_COUNT_SHIFT;
4710         stats->ass_err_count = this_mac->mac_base->MMSL_ERR_STATS & GEM_ASS_ERR_COUNT;
4711         stats->ass_ok_count  = this_mac->mac_base->MMSL_ASS_OK_COUNT;
4712         stats->frag_count_rx = this_mac->mac_base->MMSL_FRAG_COUNT_RX;
4713         stats->frag_count_tx = this_mac->mac_base->MMSL_FRAG_COUNT_TX;
4714     }
4715 }
4716 
4717 
4718 /******************************************************************************
4719  * See mss_ethernet_mac.h for details of how to use this function.
4720  */
4721 
MSS_MAC_set_tx_cutthru(const mss_mac_instance_t * this_mac,uint32_t level)4722 void MSS_MAC_set_tx_cutthru(const mss_mac_instance_t *this_mac, uint32_t level)
4723 {
4724     volatile uint32_t *p_reg;
4725     uint32_t mask;
4726 
4727     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4728     {
4729         p_reg = (0U != this_mac->is_emac) ? &this_mac->emac_base->PBUF_TXCUTTHRU : &this_mac->mac_base->PBUF_TXCUTTHRU;
4730         mask  = (0U != this_mac->is_emac) ? GEM_DMA_EMAC_CUTTHRU_THRESHOLD : GEM_DMA_TX_CUTTHRU_THRESHOLD;
4731 
4732         if(0U == level) /* Disabling cutthru? */
4733         {
4734             *p_reg = 0U;
4735         }
4736         else
4737         {
4738             *p_reg = GEM_DMA_CUTTHRU | (level & mask);
4739         }
4740     }
4741 }
4742 
4743 
4744 /******************************************************************************
4745  * See mss_ethernet_mac.h for details of how to use this function.
4746  */
4747 
MSS_MAC_set_rx_cutthru(const mss_mac_instance_t * this_mac,uint32_t level)4748 void MSS_MAC_set_rx_cutthru(const mss_mac_instance_t *this_mac, uint32_t level)
4749 {
4750     volatile uint32_t *p_reg;
4751     uint32_t mask;
4752 
4753     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4754     {
4755         p_reg = (0U != this_mac->is_emac) ? &this_mac->emac_base->PBUF_RXCUTTHRU : &this_mac->mac_base->PBUF_RXCUTTHRU;
4756         mask  = (0U != this_mac->is_emac) ? GEM_DMA_EMAC_CUTTHRU_THRESHOLD : GEM_DMA_RX_CUTTHRU_THRESHOLD;
4757 
4758         if(0U == level) /* Disabling cutthru? */
4759         {
4760             *p_reg = 0U;
4761         }
4762         else
4763         {
4764             *p_reg = GEM_DMA_CUTTHRU | (level & mask);
4765         }
4766     }
4767 }
4768 
4769 
4770 /******************************************************************************
4771  * See mss_ethernet_mac.h for details of how to use this function.
4772  */
4773 
MSS_MAC_get_tx_cutthru(const mss_mac_instance_t * this_mac)4774 uint32_t MSS_MAC_get_tx_cutthru(const mss_mac_instance_t *this_mac)
4775 {
4776     uint32_t temp_reg = 0U;
4777     volatile uint32_t *p_reg;
4778     uint32_t mask;
4779 
4780     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4781     {
4782         p_reg = (0U != this_mac->is_emac) ? &this_mac->emac_base->PBUF_TXCUTTHRU : &this_mac->mac_base->PBUF_TXCUTTHRU;
4783         mask  = (0U != this_mac->is_emac) ? GEM_DMA_EMAC_CUTTHRU_THRESHOLD : GEM_DMA_TX_CUTTHRU_THRESHOLD;
4784 
4785         temp_reg = *p_reg;
4786         if(0U == (temp_reg & GEM_DMA_CUTTHRU))
4787         {
4788             temp_reg = 0U;
4789         }
4790         else
4791         {
4792             temp_reg &= mask;
4793         }
4794     }
4795 
4796     return(temp_reg);
4797 }
4798 
4799 
4800 /******************************************************************************
4801  * See mss_ethernet_mac.h for details of how to use this function.
4802  */
4803 
MSS_MAC_get_rx_cutthru(const mss_mac_instance_t * this_mac)4804 uint32_t MSS_MAC_get_rx_cutthru(const mss_mac_instance_t *this_mac)
4805 {
4806     uint32_t temp_reg = 0U;
4807     volatile uint32_t *p_reg;
4808     uint32_t mask;
4809 
4810     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4811     {
4812         p_reg = (0U != this_mac->is_emac) ? &this_mac->emac_base->PBUF_RXCUTTHRU : &this_mac->mac_base->PBUF_RXCUTTHRU;
4813         mask  = (0U != this_mac->is_emac) ? GEM_DMA_EMAC_CUTTHRU_THRESHOLD : GEM_DMA_RX_CUTTHRU_THRESHOLD;
4814 
4815         temp_reg = *p_reg;
4816         if(0U == (temp_reg & GEM_DMA_CUTTHRU))
4817         {
4818             temp_reg = 0U;
4819         }
4820         else
4821         {
4822             temp_reg &= mask;
4823         }
4824     }
4825 
4826     return(temp_reg);
4827 }
4828 
4829 
4830 /******************************************************************************
4831  * See mss_ethernet_mac.h for details of how to use this function.
4832  */
4833 
MSS_MAC_tx_enable(const mss_mac_instance_t * this_mac)4834 void MSS_MAC_tx_enable(const mss_mac_instance_t *this_mac)
4835 {
4836     /* Don't do this if already done in case it has side effects... */
4837     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4838     {
4839         if(0U != this_mac->is_emac)
4840         {
4841             if(0U == (this_mac->emac_base->NETWORK_CONTROL & GEM_ENABLE_TRANSMIT))
4842             {
4843                 this_mac->emac_base->NETWORK_CONTROL |= GEM_ENABLE_TRANSMIT;
4844             }
4845         }
4846         else
4847         {
4848             if(0U == (this_mac->mac_base->NETWORK_CONTROL & GEM_ENABLE_TRANSMIT))
4849             {
4850                 this_mac->mac_base->NETWORK_CONTROL |= GEM_ENABLE_TRANSMIT;
4851             }
4852         }
4853     }
4854 }
4855 
4856 
4857 /******************************************************************************
4858  * See mss_ethernet_mac.h for details of how to use this function.
4859  */
4860 
MSS_MAC_set_jumbo_frames_mode(const mss_mac_instance_t * this_mac,bool state)4861 void MSS_MAC_set_jumbo_frames_mode(const mss_mac_instance_t *this_mac, bool state)
4862 {
4863     volatile uint32_t *p_reg = &this_mac->mac_base->NETWORK_CONFIG;
4864 
4865     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4866     {
4867         if(0U != this_mac->is_emac)
4868         {
4869             p_reg = &this_mac->emac_base->NETWORK_CONFIG;
4870         }
4871 
4872         if(0U != this_mac->jumbo_frame_enable) /* Only look at this if the feature is enabled in config */
4873         {
4874             if(state)
4875             {
4876                 *p_reg |= GEM_JUMBO_FRAMES;
4877             }
4878             else
4879             {
4880                 *p_reg &= ~GEM_JUMBO_FRAMES;
4881             }
4882         }
4883         else /* Ensure it is disabled if not allowed... */
4884         {
4885             *p_reg &= ~GEM_JUMBO_FRAMES;
4886         }
4887     }
4888 }
4889 
4890 
4891 /******************************************************************************
4892  * See mss_ethernet_mac.h for details of how to use this function.
4893  */
4894 
MSS_MAC_get_jumbo_frames_mode(const mss_mac_instance_t * this_mac)4895 bool MSS_MAC_get_jumbo_frames_mode(const mss_mac_instance_t *this_mac)
4896 {
4897     bool ret_val = false;
4898     volatile uint32_t *p_reg = &this_mac->mac_base->NETWORK_CONFIG;
4899 
4900     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4901     {
4902         if(0U != this_mac->is_emac)
4903         {
4904             p_reg = &this_mac->emac_base->NETWORK_CONFIG;
4905         }
4906 
4907         ret_val = ((*p_reg & GEM_JUMBO_FRAMES) != 0U);
4908     }
4909 
4910     return(ret_val);
4911 }
4912 
4913 
4914 /******************************************************************************
4915  * See mss_ethernet_mac.h for details of how to use this function.
4916  */
4917 
MSS_MAC_set_jumbo_frame_length(const mss_mac_instance_t * this_mac,uint32_t length_in)4918 void MSS_MAC_set_jumbo_frame_length(const mss_mac_instance_t *this_mac, uint32_t length_in)
4919 {
4920     volatile uint32_t *p_reg = &this_mac->mac_base->JUMBO_MAX_LENGTH;
4921     uint32_t length = length_in; /* Avoids warning about modifying parameter passed by value */
4922 
4923     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4924     {
4925         if(0U != this_mac->is_emac)
4926         {
4927             p_reg = &this_mac->emac_base->JUMBO_MAX_LENGTH;
4928         }
4929 
4930         /* Set up maximum jumbo frame size - but bounds check first  */
4931         if(length > MSS_MAC_JUMBO_MAX)
4932         {
4933             length = MSS_MAC_JUMBO_MAX;
4934         }
4935 
4936         if(0U != this_mac->jumbo_frame_enable) /* Only look at this if the feature is enabled in config */
4937         {
4938             *p_reg = length;
4939         }
4940         else /* Ensure it is set to reset value if not allowed... */
4941         {
4942             *p_reg = MSS_MAC_JUMBO_MAX;
4943         }
4944     }
4945 }
4946 
4947 
4948 /******************************************************************************
4949  * See mss_ethernet_mac.h for details of how to use this function.
4950  */
4951 
MSS_MAC_get_jumbo_frame_length(const mss_mac_instance_t * this_mac)4952 uint32_t MSS_MAC_get_jumbo_frame_length(const mss_mac_instance_t *this_mac)
4953 {
4954     uint32_t ret_val = 0;
4955     volatile uint32_t *p_reg = &this_mac->mac_base->JUMBO_MAX_LENGTH;
4956 
4957     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4958     {
4959         if(0U != this_mac->is_emac)
4960         {
4961             p_reg = &this_mac->emac_base->JUMBO_MAX_LENGTH;
4962         }
4963 
4964         ret_val = *p_reg;
4965     }
4966 
4967     return(ret_val);
4968 }
4969 
4970 
4971 /******************************************************************************
4972  * See mss_ethernet_mac.h for details of how to use this function.
4973  */
4974 
MSS_MAC_set_pause_frame_copy_to_mem(const mss_mac_instance_t * this_mac,bool state)4975 void MSS_MAC_set_pause_frame_copy_to_mem(const mss_mac_instance_t *this_mac, bool state)
4976 {
4977     volatile uint32_t *p_reg = &this_mac->mac_base->NETWORK_CONFIG;
4978 
4979     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
4980     {
4981         if(0U != this_mac->is_emac)
4982         {
4983             p_reg = &this_mac->emac_base->NETWORK_CONFIG;
4984         }
4985         /*
4986          * Logic is inverted as enabling copy to memory means disabling
4987          * GEM_DISABLE_COPY_OF_PAUSE_FRAMES
4988          */
4989         if(state)
4990         {
4991             *p_reg &= ~GEM_DISABLE_COPY_OF_PAUSE_FRAMES;
4992         }
4993         else
4994         {
4995             *p_reg |= GEM_DISABLE_COPY_OF_PAUSE_FRAMES;
4996         }
4997     }
4998 }
4999 
5000 
5001 /******************************************************************************
5002  * See mss_ethernet_mac.h for details of how to use this function.
5003  */
5004 
MSS_MAC_get_pause_frame_copy_to_mem(const mss_mac_instance_t * this_mac)5005 bool MSS_MAC_get_pause_frame_copy_to_mem(const mss_mac_instance_t *this_mac)
5006 {
5007     bool ret_val = false;
5008     volatile uint32_t *p_reg = &this_mac->mac_base->NETWORK_CONFIG;
5009 
5010     if(MSS_MAC_AVAILABLE == this_mac->mac_available)
5011     {
5012         if(0U != this_mac->is_emac)
5013         {
5014             p_reg = &this_mac->emac_base->NETWORK_CONFIG;
5015         }
5016 
5017         /*
5018          * Logic is inverted as enabling copy to memory means disabling
5019          * GEM_DISABLE_COPY_OF_PAUSE_FRAMES
5020          */
5021         ret_val = 0U == (*p_reg & GEM_DISABLE_COPY_OF_PAUSE_FRAMES);
5022     }
5023 
5024     return(ret_val);
5025 }
5026 
5027 
5028 /**************************************************************************/
5029 /* Private Function definitions                                           */
5030 /**************************************************************************/
5031 
5032 /******************************************************************************
5033  * This is default "Receive packet interrupt handler. This function finds the
5034  * descriptor that received the packet and caused the interrupt.
5035  * This informs the received packet size to the application and
5036  * relinquishes the packet buffer from the associated DMA descriptor.
5037  */
5038 static void
rxpkt_handler(mss_mac_instance_t * this_mac,uint64_t queue_no)5039 rxpkt_handler
5040 (
5041     mss_mac_instance_t *this_mac, uint64_t queue_no
5042 )
5043 {
5044     mss_mac_queue_t *this_queue = &this_mac->queue[queue_no];
5045     mss_mac_rx_desc_t * cdesc = &this_queue->rx_desc_tab[this_queue->first_rx_desc_index];
5046     uint64_t burst = MSS_MAC_RX_RING_SIZE;
5047 
5048     if(0U != (cdesc->addr_low & GEM_RX_DMA_USED)) /* Check in case we already got it... */
5049     {
5050         /* Execution comes here because at-least one packet is received. */
5051         do
5052         {
5053             uint8_t * p_rx_packet;
5054             uint32_t pckt_length;
5055 #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
5056             uint64_t addr_temp;
5057 #else
5058             uint32_t addr_temp;
5059 #endif
5060 
5061             ++this_queue->nb_available_rx_desc;
5062 #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
5063             addr_temp  = (uint64_t)(cdesc->addr_low & ~(GEM_RX_DMA_WRAP | GEM_RX_DMA_USED | GEM_RX_DMA_TS_PRESENT));
5064             addr_temp |= (uint64_t)cdesc->addr_high << 32;
5065 #else
5066             addr_temp = (cdesc->addr_low & ~(GEM_RX_DMA_WRAP | GEM_RX_DMA_USED | GEM_RX_DMA_TS_PRESENT));
5067 #endif
5068             p_rx_packet = (uint8_t *)addr_temp;
5069             /*
5070              * Pass received packet up to application layer - if enabled...
5071              *
5072              * Note if rx_packet comes back as 0 we can't recover and will leave a
5073              * used packet stuck in the queue...
5074              */
5075 #if !defined(MSS_MAC_UNH_TEST)
5076             if((NULL_POINTER != this_queue->pckt_rx_callback) && (NULL_POINTER != p_rx_packet) && (0U == this_mac->rx_discard))
5077 #endif
5078             {
5079                 pckt_length = cdesc->status & (GEM_RX_DMA_BUFF_LEN | GEM_RX_DMA_JUMBO_BIT_13);
5080                 this_queue->ingress += pckt_length;
5081 
5082                 this_queue->pckt_rx_callback(this_mac, queue_no, p_rx_packet, pckt_length, cdesc, this_queue->rx_caller_info[this_queue->first_rx_desc_index]);
5083             }
5084 
5085 #if !defined(MSS_MAC_UNH_TEST)
5086             if((NULL_POINTER != p_rx_packet) && (0U != this_mac->rx_discard))
5087             {
5088                 /*
5089                  * Need to return receive packet buffer to the queue as rx handler
5090                  * hasn't been called to do it for us...
5091                  */
5092                 (void)MSS_MAC_receive_pkt(this_mac, queue_no, p_rx_packet, this_queue->rx_caller_info[this_queue->first_rx_desc_index], MSS_MAC_INT_ENABLE);
5093             }
5094 #endif
5095 
5096             /* Point the curr_rx_desc to next descriptor in the ring */
5097             /* Wrap around in case next descriptor is pointing to last in the ring */
5098             ++this_queue->first_rx_desc_index;
5099             this_queue->first_rx_desc_index %= MSS_MAC_RX_RING_SIZE;
5100 
5101             cdesc = &this_queue->rx_desc_tab[this_queue->first_rx_desc_index];
5102             burst--;
5103         } while(0 != (cdesc->addr_low & GEM_RX_DMA_USED) && (0 != burst)); /* loop while there are packets available */
5104     }
5105 
5106     if(0U == (this_mac->mac_base->NETWORK_CONTROL & GEM_ENABLE_RECEIVE))
5107     {
5108         this_mac->mac_base->NETWORK_CONTROL |= GEM_ENABLE_RECEIVE;
5109     }
5110 }
5111 
5112 
5113 /******************************************************************************
5114  * This is default "Transmit packet interrupt handler. This function finds the
5115  * descriptor that transmitted the packet and caused the interrupt.
5116  * This relinquishes the packet buffer from the associated DMA descriptor.
5117  */
5118 
5119 static void
txpkt_handler(mss_mac_instance_t * this_mac,uint64_t queue_no)5120 txpkt_handler
5121 (
5122         mss_mac_instance_t *this_mac, uint64_t queue_no
5123 )
5124 {
5125 #if defined(MSS_MAC_SIMPLE_TX_QUEUE)
5126     mss_mac_queue_t *this_queue = &this_mac->queue[queue_no];
5127     mss_mac_tx_desc_t *p_current_desc;
5128     uint32_t finished;
5129 
5130     /*
5131      * Simple multi packet TX queue where only the one packet buffer is used
5132      * per frame but we do have 1 extra descriptor to stop DMA engine running
5133      * over itself...
5134      */
5135 
5136     p_current_desc = &this_queue->tx_desc_tab[this_queue->current_tx_desc];
5137     finished = 0;
5138     while(!finished)
5139     {
5140         if(this_queue->nb_available_tx_desc == MSS_MAC_TX_RING_SIZE)
5141         {
5142             *this_queue->transmit_q_ptr = (uint32_t)((uint64_t)this_queue->tx_desc_tab) | 1UL; /* Disable the TX queue */
5143             finished = 1;
5144         }
5145         else
5146         {
5147             if(p_current_desc->status & GEM_TX_DMA_USED)
5148             {
5149                 if(NULL_POINTER != this_queue->pckt_tx_callback)
5150                 {
5151                     this_queue->pckt_tx_callback(this_mac, queue_no, p_current_desc, this_queue->tx_caller_info[this_queue->current_tx_desc]);
5152                 }
5153                 this_queue->nb_available_tx_desc++;
5154                 p_current_desc++;
5155                 this_queue->current_tx_desc++;
5156             }
5157             else
5158             {
5159                 finished = 1;
5160             }
5161         }
5162     }
5163 #else
5164 #error "Multi packet TX not implemented!"
5165 #endif
5166 }
5167 
5168 
5169 /******************************************************************************
5170  *
5171  */
tx_desc_ring_init(mss_mac_instance_t * this_mac)5172 static void tx_desc_ring_init(mss_mac_instance_t *this_mac)
5173 {
5174     int32_t inc;
5175     int32_t queue_no;
5176 
5177     for(queue_no = 0; queue_no < MSS_MAC_QUEUE_COUNT; queue_no++)
5178     {
5179 #if defined(MSS_MAC_USE_DDR)
5180         this_mac->queue[queue_no].tx_desc_tab = g_mss_mac_ddr_ptr;
5181         g_mss_mac_ddr_ptr += MSS_MAC_TX_RING_SIZE * sizeof(mss_mac_tx_desc_t);
5182 #endif
5183         for(inc = 0; inc < MSS_MAC_TX_RING_SIZE; ++inc)
5184         {
5185             this_mac->queue[queue_no].tx_desc_tab[inc].addr_low = 0U;
5186 #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
5187             this_mac->queue[queue_no].tx_desc_tab[inc].addr_high = 0U;
5188 #endif
5189             this_mac->queue[queue_no].tx_desc_tab[inc].status = GEM_TX_DMA_USED;
5190         }
5191 
5192         inc--; /* Step back to last buffer descriptor and mark as end of list */
5193         this_mac->queue[queue_no].tx_desc_tab[inc].status |= GEM_TX_DMA_WRAP;
5194     }
5195 }
5196 
5197 
5198 /******************************************************************************
5199  *
5200  */
rx_desc_ring_init(mss_mac_instance_t * this_mac)5201 static void rx_desc_ring_init(mss_mac_instance_t *this_mac)
5202 {
5203     uint32_t inc;
5204     int32_t queue_no;
5205 
5206     for(queue_no = 0; queue_no < MSS_MAC_QUEUE_COUNT; queue_no++)
5207     {
5208 #if defined(MSS_MAC_USE_DDR)
5209         this_mac->queue[queue_no].rx_desc_tab = g_mss_mac_ddr_ptr;
5210         g_mss_mac_ddr_ptr += MSS_MAC_RX_RING_SIZE * sizeof(mss_mac_rx_desc_t);
5211 #endif
5212 
5213         for(inc = 0U; inc < MSS_MAC_RX_RING_SIZE; ++inc)
5214         {
5215             this_mac->queue[queue_no].rx_desc_tab[inc].addr_low = 0U; /* Mark buffers as used for now in case DMA gets enabled before we attach a buffer */
5216 #if defined(MSS_MAC_64_BIT_ADDRESS_MODE)
5217             this_mac->queue[queue_no].rx_desc_tab[inc].addr_high = 0U;
5218 #endif
5219             this_mac->queue[queue_no].rx_desc_tab[inc].status = 0U;
5220         }
5221 
5222         inc--; /* Step back to last buffer descriptor and mark as end of list */
5223         this_mac->queue[queue_no].rx_desc_tab[inc].addr_low |= GEM_RX_DMA_WRAP;
5224     }
5225 }
5226 
5227 
5228 /******************************************************************************
5229  *
5230  */
assign_station_addr(mss_mac_instance_t * this_mac,const uint8_t mac_addr[MSS_MAC_MAC_LEN])5231 static void assign_station_addr
5232 (
5233     mss_mac_instance_t *this_mac,
5234     const uint8_t mac_addr[MSS_MAC_MAC_LEN]
5235 )
5236 {
5237     uint32_t address32_l;
5238     uint32_t address32_h;
5239 
5240     ASSERT(NULL_POINTER != mac_addr);
5241 
5242     if((NULL_POINTER != mac_addr) && (NULL_POINTER != this_mac))
5243     {
5244         /* Update current instance data */
5245         (void)memcpy(this_mac->mac_addr, mac_addr, MSS_MAC_MAC_LEN);
5246 
5247         /* Assemble correct register values */
5248         address32_l  = ((uint32_t)mac_addr[3]) << 24;
5249         address32_l |= ((uint32_t)mac_addr[2]) << 16;
5250         address32_l |= ((uint32_t)mac_addr[1]) << 8;
5251         address32_l |= ((uint32_t)mac_addr[0]);
5252         address32_h =  ((uint32_t)mac_addr[5]) << 8;
5253         address32_h |= ((uint32_t)mac_addr[4]);
5254 
5255         /* Update hardware registers */
5256         if(0U != this_mac->is_emac)
5257         {
5258             this_mac->emac_base->SPEC_ADD1_BOTTOM = address32_l;
5259             this_mac->emac_base->SPEC_ADD1_TOP    = address32_h;
5260             /*
5261              * If being done from init for first time we also make sure the
5262              * specific address filters are disabled...
5263              */
5264             if(this_mac->mac_available != MSS_MAC_AVAILABLE)
5265             {
5266                 this_mac->emac_base->SPEC_ADD2_TOP    = 0U;
5267                 this_mac->emac_base->SPEC_ADD2_BOTTOM = 0U;
5268                 this_mac->emac_base->SPEC_ADD3_TOP    = 0U;
5269                 this_mac->emac_base->SPEC_ADD3_BOTTOM = 0U;
5270                 this_mac->emac_base->SPEC_ADD4_TOP    = 0U;
5271                 this_mac->emac_base->SPEC_ADD4_BOTTOM = 0U;
5272             }
5273         }
5274         else
5275         {
5276             this_mac->mac_base->SPEC_ADD1_BOTTOM  = address32_l;
5277             this_mac->mac_base->SPEC_ADD1_TOP     = address32_h;
5278             /*
5279              * If being done from init for first time we also make sure the
5280              * specific address filters are disabled...
5281              */
5282             if(this_mac->mac_available != MSS_MAC_AVAILABLE)
5283             {
5284                 this_mac->mac_base->SPEC_ADD2_TOP     = 0U;
5285                 this_mac->mac_base->SPEC_ADD2_BOTTOM  = 0U;
5286                 this_mac->mac_base->SPEC_ADD3_TOP     = 0U;
5287                 this_mac->mac_base->SPEC_ADD3_BOTTOM  = 0U;
5288                 this_mac->mac_base->SPEC_ADD4_TOP     = 0U;
5289                 this_mac->mac_base->SPEC_ADD4_BOTTOM  = 0U;
5290             }
5291         }
5292     }
5293 }
5294 
5295 
5296 /*******************************************************************************
5297  * Auto-detect the PHY's address by attempting to read the PHY identification
5298  * register containing the PHY manufacturer's identifier.
5299  * Attempting to read a PHY register using an incorrect PHY address will result
5300  * in a value with all bits set to one on the MDIO bus. Reading any other value
5301  * means that a PHY responded to the read request, therefore we have found the
5302  * PHY's address.
5303  * This function returns the detected PHY's address or 32 (PHY_ADDRESS_MAX + 1)
5304  * if no PHY is responding.
5305  */
probe_phy(const mss_mac_instance_t * this_mac)5306 static uint8_t probe_phy(const mss_mac_instance_t *this_mac)
5307 {
5308     uint8_t phy_address = PHY_ADDRESS_MIN;
5309     const uint16_t ALL_BITS_HIGH = 0xFFFFU;
5310     const uint8_t PHYREG_PHYID1R = 0x02U;   /* PHY Identifier 1 register address. */
5311     uint32_t found;
5312 
5313     do
5314     {
5315         uint16_t reg;
5316 
5317         reg = MSS_MAC_read_phy_reg(this_mac, phy_address, PHYREG_PHYID1R);
5318         if (reg != ALL_BITS_HIGH)
5319         {
5320             found = 1U;
5321         }
5322         else
5323         {
5324             found = 0U;
5325             ++phy_address;
5326         }
5327     }
5328     while ((phy_address <= PHY_ADDRESS_MAX) && (0U == found));
5329 
5330     return phy_address;
5331 }
5332 
5333 
5334 /*******************************************************************************
5335  * MSS MAC TBI interface
5336  */
msgmii_init(const mss_mac_instance_t * this_mac)5337 static void msgmii_init(const mss_mac_instance_t *this_mac)
5338 {
5339     if(GMII_SGMII == this_mac->interface_type)
5340     {
5341         if(0U == this_mac->is_emac)
5342         {
5343             this_mac->mac_base->PCS_CONTROL = 0x9000UL; /* Reset and enable autonegotiation */
5344         }
5345     }
5346 
5347     if(TBI == this_mac->interface_type)
5348     {
5349         if(0U == this_mac->is_emac)
5350         {
5351             this_mac->mac_base->PCS_CONTROL = 0x9000UL; /* Reset and enable autonegotiation */
5352         }
5353     }
5354 }
5355 
5356 
5357 /*******************************************************************************
5358  *
5359  */
msgmii_autonegotiate(const mss_mac_instance_t * this_mac)5360 void msgmii_autonegotiate(const mss_mac_instance_t *this_mac)
5361  {
5362     uint16_t phy_reg;
5363     uint16_t autoneg_complete;
5364     uint8_t link_fullduplex;
5365     mss_mac_speed_t link_speed;
5366     uint8_t copper_link_up;
5367 
5368     volatile uint32_t sgmii_aneg_timeout = 100000U;
5369 
5370     copper_link_up = this_mac->phy_get_link_status(this_mac, &link_speed, &link_fullduplex);
5371 
5372     if(MSS_MAC_LINK_UP == copper_link_up)
5373     {
5374         /* Initiate auto-negotiation on the TBI SGMII link. */
5375         if(TBI == this_mac->interface_type)
5376         {
5377             phy_reg = (uint16_t)this_mac->mac_base->PCS_CONTROL;
5378             phy_reg |= 0x1000U;
5379             this_mac->mac_base->PCS_CONTROL = phy_reg;
5380             phy_reg |= 0x0200U;
5381             this_mac->mac_base->PCS_CONTROL = phy_reg;
5382 
5383             /* Wait for SGMII auto-negotiation to complete. */
5384             do
5385             {
5386                 phy_reg = (uint16_t)this_mac->mac_base->PCS_STATUS;
5387                 autoneg_complete = phy_reg & BMSR_AUTO_NEGOTIATION_COMPLETE;
5388                 --sgmii_aneg_timeout;
5389             } while(((0U == autoneg_complete) && (sgmii_aneg_timeout != 0U)) || (0xFFFFU == phy_reg));
5390         }
5391     }
5392 }
5393 
5394 
5395 #if 0
5396 /*******************************************************************************
5397  * SGMII or 1000BaseX interface with CoreSGMII
5398  */
5399 #if (MSS_MAC_PHY_INTERFACE == SGMII)
5400 
5401 #define CORE_SGMII_PHY_ADDR    MSS_MAC_INTERFACE_MDIO_ADDR
5402 /*******************************************************************************
5403  *
5404  */
5405 static void coresgmii_init(void)
5406 {
5407     uint16_t phy_reg;
5408 
5409     /* Reset C-SGMII. */
5410     MSS_MAC_write_phy_reg(CORE_SGMII_PHY_ADDR, 0x00U, 0x9000U);
5411     /* Register 0x04 of C-SGMII must be always be set to 0x0001. */
5412     MSS_MAC_write_phy_reg(CORE_SGMII_PHY_ADDR, 0x04U, 0x0001U);
5413 
5414     /* Enable auto-negotiation inside CoreSGMII block. */
5415     phy_reg = MSS_MAC_read_phy_reg(CORE_SGMII_PHY_ADDR, 0x00U);
5416     phy_reg |= 0x1000U;
5417     MSS_MAC_write_phy_reg(CORE_SGMII_PHY_ADDR, 0x00U, phy_reg);
5418 }
5419 
5420 
5421 /*******************************************************************************
5422  *
5423  */
5424 static void coresgmii_autonegotiate(void)
5425 {
5426     uint16_t phy_reg;
5427     uint16_t autoneg_complete;
5428     volatile uint32_t sgmii_aneg_timeout = 1000000U;
5429 
5430     uint8_t link_fullduplex;
5431     mss_mac_speed_t link_speed;
5432     uint8_t copper_link_up;
5433 
5434     copper_link_up = MSS_MAC_phy_get_link_status(&link_speed, &link_fullduplex);
5435 
5436     if(MSS_MAC_LINK_UP == copper_link_up)
5437     {
5438         SYSREG->MAC_CR = (SYSREG->MAC_CR & ~MAC_CONFIG_SPEED_MASK) | link_speed;
5439 
5440         /* Configure duplex mode */
5441         if(MSS_MAC_HALF_DUPLEX == link_fullduplex)
5442         {
5443             /* half duplex */
5444             MAC->CFG2 &= ~CFG2_FDX_MASK;
5445         }
5446         else
5447         {
5448             /* full duplex */
5449             MAC->CFG2 |= CFG2_FDX_MASK;
5450         }
5451         /* Initiate auto-negotiation on the SGMII link. */
5452         phy_reg = MSS_MAC_read_phy_reg(CORE_SGMII_PHY_ADDR, 0x00U);
5453         phy_reg |= 0x1000U;
5454         MSS_MAC_write_phy_reg(CORE_SGMII_PHY_ADDR, 0x00U, phy_reg);
5455         phy_reg |= 0x0200U;
5456         MSS_MAC_write_phy_reg(CORE_SGMII_PHY_ADDR, 0x00U, phy_reg);
5457 
5458         /* Wait for SGMII auto-negotiation to complete. */
5459         do {
5460             phy_reg = MSS_MAC_read_phy_reg(CORE_SGMII_PHY_ADDR, MII_BMSR);
5461             autoneg_complete = phy_reg & BMSR_AUTO_NEGOTIATION_COMPLETE;
5462             --sgmii_aneg_timeout;
5463         } while(((0U == autoneg_complete) && (sgmii_aneg_timeout != 0U)) || (0xFFFFU == phy_reg));
5464     }
5465 }
5466 
5467 
5468 /*******************************************************************************
5469  * Generate clock 2.5/25/125MHz for 10/100/1000Mbps using Clock Condition Circuit(CCC)
5470  */
5471 static void coresgmii_set_link_speed(uint32_t speed)
5472 {
5473     uint16_t phy_reg;
5474 
5475     phy_reg = MSS_MAC_read_phy_reg(CORE_SGMII_PHY_ADDR, 0x11U);
5476     phy_reg |= (speed << 2);
5477     MSS_MAC_write_phy_reg(CORE_SGMII_PHY_ADDR, 0x11U, phy_reg);
5478 }
5479 
5480 #endif /* #if (MSS_MAC_PHY_INTERFACE == SGMII) */
5481 #endif
5482 
5483 
5484 /*******************************************************************************
5485  * Setup hardware addresses etc for instance structure(s).
5486  */
instances_init(mss_mac_instance_t * this_mac,mss_mac_cfg_t * cfg)5487 static void instances_init(mss_mac_instance_t *this_mac, mss_mac_cfg_t *cfg)
5488 {
5489 #if defined(TARGET_ALOE)
5490     /* These are unused for Aloe as there is only one pMAC and no alternate
5491      * address support required
5492      */
5493     (void)this_mac;
5494     (void)cfg;
5495 
5496     (void)memset(&g_mac0, 0, sizeof(g_mac0));
5497 
5498     g_mac0.use_hi_address = cfg->use_hi_address; /* Not really needed but to be consistent... */
5499 
5500     g_mac0.is_emac                 = 0U;
5501     g_mac0.mac_base                = (MAC_TypeDef  *)MSS_MAC0_BASE;
5502     g_mac0.emac_base               = (eMAC_TypeDef *)MSS_MAC0_BASE;
5503     g_mac0.mac_q_int[0]            = ethernet_PLIC_53;
5504     g_mac0.queue[0].int_status     = &g_mac0.mac_base->INT_STATUS;
5505     g_mac0.queue[0].int_mask       = &g_mac0.mac_base->INT_MASK;
5506     g_mac0.queue[0].int_enable     = &g_mac0.mac_base->INT_ENABLE;
5507     g_mac0.queue[0].int_disable    = &g_mac0.mac_base->INT_DISABLE;
5508     g_mac0.queue[0].receive_q_ptr  = &g_mac0.mac_base->RECEIVE_Q_PTR;
5509     g_mac0.queue[0].transmit_q_ptr = &g_mac0.mac_base->TRANSMIT_Q_PTR;
5510     g_mac0.queue[0].dma_rxbuf_size = &g_mac0.mac_base->DMA_RXBUF_SIZE_Q1; /* Not really true as this is done differently for queue 0 */
5511 #endif
5512 #if defined(TARGET_G5_SOC)
5513     (void)memset(this_mac, 0, sizeof(mss_mac_instance_t)); /* Start with blank canvas */
5514 
5515     this_mac->use_hi_address = cfg->use_hi_address; /* Need to remember this for sanity checking */
5516     this_mac->use_local_ints = cfg->use_local_ints; /* Need to remember this for interrupt management */
5517 
5518     if(&g_mac0 == this_mac)
5519     {
5520         if(MSS_MAC_DISABLE == cfg->use_hi_address)
5521         {
5522             this_mac->mac_base    = (MAC_TypeDef  *)MSS_MAC0_BASE;
5523             this_mac->emac_base   = (eMAC_TypeDef *)MSS_EMAC0_BASE;
5524 
5525             SYSREG->APBBUS_CR &= ~MSS_MAC_GEM0_ABP_BIT;
5526         }
5527         else
5528         {
5529             this_mac->mac_base    = (MAC_TypeDef  *)MSS_MAC0_BASE_HI;
5530             this_mac->emac_base   = (eMAC_TypeDef *)MSS_EMAC0_BASE_HI;
5531 
5532             SYSREG->APBBUS_CR |= MSS_MAC_GEM0_ABP_BIT;
5533         }
5534 
5535         if(0U != this_mac->use_local_ints)
5536         {
5537             PLIC_DisableIRQ(MAC0_INT_PLIC);
5538             PLIC_DisableIRQ(MAC0_QUEUE1_PLIC);
5539             PLIC_DisableIRQ(MAC0_QUEUE2_PLIC);
5540             PLIC_DisableIRQ(MAC0_QUEUE3_PLIC);
5541             PLIC_DisableIRQ(MAC0_MMSL_PLIC);
5542 
5543             this_mac->mac_q_int[0] = MAC0_INT_U54_INT;
5544             this_mac->mac_q_int[1] = MAC0_QUEUE1_U54_INT;
5545             this_mac->mac_q_int[2] = MAC0_QUEUE2_U54_INT;
5546             this_mac->mac_q_int[3] = MAC0_QUEUE3_U54_INT;
5547             this_mac->mmsl_int     = MAC0_MMSL_U54_INT;
5548         }
5549         else
5550         {
5551             __disable_local_irq(MAC0_INT_U54_INT);
5552             __disable_local_irq(MAC0_QUEUE1_U54_INT);
5553             __disable_local_irq(MAC0_QUEUE2_U54_INT);
5554             __disable_local_irq(MAC0_QUEUE3_U54_INT);
5555             __disable_local_irq(MAC0_MMSL_U54_INT);
5556 
5557             this_mac->mac_q_int[0] = MAC0_INT_PLIC;
5558             this_mac->mac_q_int[1] = MAC0_QUEUE1_PLIC;
5559             this_mac->mac_q_int[2] = MAC0_QUEUE2_PLIC;
5560             this_mac->mac_q_int[3] = MAC0_QUEUE3_PLIC;
5561             this_mac->mmsl_int     = MAC0_MMSL_PLIC;
5562         }
5563     }
5564     else if(&g_mac1 == this_mac)
5565     {
5566         if(MSS_MAC_DISABLE == cfg->use_hi_address)
5567         {
5568             this_mac->mac_base    = (MAC_TypeDef  *)MSS_MAC1_BASE;
5569             this_mac->emac_base   = (eMAC_TypeDef *)MSS_EMAC1_BASE;
5570 
5571             SYSREG->APBBUS_CR &= ~MSS_MAC_GEM1_ABP_BIT;
5572         }
5573         else
5574         {
5575             this_mac->mac_base    = (MAC_TypeDef  *)MSS_MAC1_BASE_HI;
5576             this_mac->emac_base   = (eMAC_TypeDef *)MSS_EMAC1_BASE_HI;
5577 
5578             SYSREG->APBBUS_CR |= MSS_MAC_GEM1_ABP_BIT;
5579         }
5580 
5581         if(0U != this_mac->use_local_ints)
5582         {
5583             PLIC_DisableIRQ(MAC1_INT_PLIC);
5584             PLIC_DisableIRQ(MAC1_QUEUE1_PLIC);
5585             PLIC_DisableIRQ(MAC1_QUEUE2_PLIC);
5586             PLIC_DisableIRQ(MAC1_QUEUE3_PLIC);
5587             PLIC_DisableIRQ(MAC1_MMSL_PLIC);
5588 
5589             this_mac->mac_q_int[0] = MAC1_INT_U54_INT;
5590             this_mac->mac_q_int[1] = MAC1_QUEUE1_U54_INT;
5591             this_mac->mac_q_int[2] = MAC1_QUEUE2_U54_INT;
5592             this_mac->mac_q_int[3] = MAC1_QUEUE3_U54_INT;
5593             this_mac->mmsl_int     = MAC1_MMSL_U54_INT;
5594         }
5595         else
5596         {
5597             __disable_local_irq(MAC1_INT_U54_INT);
5598             __disable_local_irq(MAC1_QUEUE1_U54_INT);
5599             __disable_local_irq(MAC1_QUEUE2_U54_INT);
5600             __disable_local_irq(MAC1_QUEUE3_U54_INT);
5601             __disable_local_irq(MAC1_MMSL_U54_INT);
5602 
5603             this_mac->mac_q_int[0] = MAC1_INT_PLIC;
5604             this_mac->mac_q_int[1] = MAC1_QUEUE1_PLIC;
5605             this_mac->mac_q_int[2] = MAC1_QUEUE2_PLIC;
5606             this_mac->mac_q_int[3] = MAC1_QUEUE3_PLIC;
5607             this_mac->mmsl_int     = MAC1_MMSL_PLIC;
5608         }
5609     }
5610     else if(&g_emac0 == this_mac)
5611     {
5612         this_mac->is_emac = 1;
5613         if(NULL_POINTER != g_mac0.mac_base) /* If pMAC already configured must use same */
5614         {
5615             cfg->use_hi_address = g_mac0.use_hi_address;
5616         }
5617 
5618         if(MSS_MAC_DISABLE == cfg->use_hi_address)
5619         {
5620             this_mac->mac_base    = (MAC_TypeDef  *)MSS_MAC0_BASE;
5621             this_mac->emac_base   = (eMAC_TypeDef *)MSS_EMAC0_BASE;
5622 
5623             SYSREG->APBBUS_CR &= ~MSS_MAC_GEM0_ABP_BIT;
5624         }
5625         else
5626         {
5627             this_mac->mac_base    = (MAC_TypeDef  *)MSS_MAC0_BASE_HI;
5628             this_mac->emac_base   = (eMAC_TypeDef *)MSS_EMAC0_BASE_HI;
5629         }
5630 
5631         if(0U != this_mac->use_local_ints)
5632         {
5633             PLIC_DisableIRQ(MAC0_EMAC_PLIC);
5634 
5635             this_mac->mac_q_int[0] = MAC0_EMAC_U54_INT;
5636             this_mac->mac_q_int[1] = LOCAL_INT_UNUSED;
5637             this_mac->mac_q_int[2] = LOCAL_INT_UNUSED;
5638             this_mac->mac_q_int[3] = LOCAL_INT_UNUSED;
5639             this_mac->mmsl_int     = LOCAL_INT_UNUSED;
5640         }
5641         else
5642         {
5643             __disable_local_irq(MAC0_EMAC_U54_INT);
5644 
5645             this_mac->mac_q_int[0] = MAC0_EMAC_PLIC;
5646             this_mac->mac_q_int[1] = INVALID_IRQn;
5647             this_mac->mac_q_int[2] = INVALID_IRQn;
5648             this_mac->mac_q_int[3] = INVALID_IRQn;
5649             this_mac->mmsl_int     = INVALID_IRQn;
5650         }
5651     }
5652     else
5653     {
5654         if(&g_emac1 == this_mac)
5655         {
5656             this_mac->is_emac = 1U;
5657             if(MSS_MAC_DISABLE == cfg->use_hi_address)
5658             {
5659                 this_mac->mac_base    = (MAC_TypeDef  *)MSS_MAC1_BASE;
5660                 this_mac->emac_base   = (eMAC_TypeDef *)MSS_EMAC1_BASE;
5661 
5662                 SYSREG->APBBUS_CR &= ~MSS_MAC_GEM1_ABP_BIT;
5663             }
5664             else
5665             {
5666                 this_mac->mac_base    = (MAC_TypeDef  *)MSS_MAC1_BASE_HI;
5667                 this_mac->emac_base   = (eMAC_TypeDef *)MSS_EMAC1_BASE_HI;
5668 
5669                 SYSREG->APBBUS_CR |= MSS_MAC_GEM1_ABP_BIT;
5670             }
5671 
5672             if(0U != this_mac->use_local_ints)
5673             {
5674                 PLIC_DisableIRQ(MAC1_EMAC_PLIC);
5675 
5676                 this_mac->mac_q_int[0] = MAC1_EMAC_U54_INT;
5677                 this_mac->mac_q_int[1] = LOCAL_INT_UNUSED;
5678                 this_mac->mac_q_int[2] = LOCAL_INT_UNUSED;
5679                 this_mac->mac_q_int[3] = LOCAL_INT_UNUSED;
5680                 this_mac->mmsl_int     = LOCAL_INT_UNUSED;
5681             }
5682             else
5683             {
5684                 __disable_local_irq(MAC1_EMAC_U54_INT);
5685 
5686                 this_mac->mac_q_int[0] = MAC1_EMAC_PLIC;
5687                 this_mac->mac_q_int[1] = INVALID_IRQn;
5688                 this_mac->mac_q_int[2] = INVALID_IRQn;
5689                 this_mac->mac_q_int[3] = INVALID_IRQn;
5690                 this_mac->mmsl_int     = INVALID_IRQn;
5691             }
5692         }
5693     }
5694 
5695     if(0U == this_mac->is_emac)
5696     {
5697         this_mac->queue[0].int_status = &this_mac->mac_base->INT_STATUS;
5698         this_mac->queue[1].int_status = &this_mac->mac_base->INT_Q1_STATUS;
5699         this_mac->queue[2].int_status = &this_mac->mac_base->INT_Q2_STATUS;
5700         this_mac->queue[3].int_status = &this_mac->mac_base->INT_Q3_STATUS;
5701 
5702         this_mac->queue[0].int_mask = &this_mac->mac_base->INT_MASK;
5703         this_mac->queue[1].int_mask = &this_mac->mac_base->INT_Q1_MASK;
5704         this_mac->queue[2].int_mask = &this_mac->mac_base->INT_Q2_MASK;
5705         this_mac->queue[3].int_mask = &this_mac->mac_base->INT_Q3_MASK;
5706 
5707         this_mac->queue[0].int_enable = &this_mac->mac_base->INT_ENABLE;
5708         this_mac->queue[1].int_enable = &this_mac->mac_base->INT_Q1_ENABLE;
5709         this_mac->queue[2].int_enable = &this_mac->mac_base->INT_Q2_ENABLE;
5710         this_mac->queue[3].int_enable = &this_mac->mac_base->INT_Q3_ENABLE;
5711 
5712         this_mac->queue[0].int_disable = &this_mac->mac_base->INT_DISABLE;
5713         this_mac->queue[1].int_disable = &this_mac->mac_base->INT_Q1_DISABLE;
5714         this_mac->queue[2].int_disable = &this_mac->mac_base->INT_Q2_DISABLE;
5715         this_mac->queue[3].int_disable = &this_mac->mac_base->INT_Q3_DISABLE;
5716 
5717         this_mac->queue[0].receive_q_ptr = &this_mac->mac_base->RECEIVE_Q_PTR;
5718         this_mac->queue[1].receive_q_ptr = &this_mac->mac_base->RECEIVE_Q1_PTR;
5719         this_mac->queue[2].receive_q_ptr = &this_mac->mac_base->RECEIVE_Q2_PTR;
5720         this_mac->queue[3].receive_q_ptr = &this_mac->mac_base->RECEIVE_Q3_PTR;
5721 
5722         this_mac->queue[0].transmit_q_ptr = &this_mac->mac_base->TRANSMIT_Q_PTR;
5723         this_mac->queue[1].transmit_q_ptr = &this_mac->mac_base->TRANSMIT_Q1_PTR;
5724         this_mac->queue[2].transmit_q_ptr = &this_mac->mac_base->TRANSMIT_Q2_PTR;
5725         this_mac->queue[3].transmit_q_ptr = &this_mac->mac_base->TRANSMIT_Q3_PTR;
5726 
5727         this_mac->queue[0].dma_rxbuf_size = &this_mac->mac_base->DMA_RXBUF_SIZE_Q1; /* Not really true as this is done differently for queue 0 */
5728         this_mac->queue[1].dma_rxbuf_size = &this_mac->mac_base->DMA_RXBUF_SIZE_Q1;
5729         this_mac->queue[2].dma_rxbuf_size = &this_mac->mac_base->DMA_RXBUF_SIZE_Q2;
5730         this_mac->queue[3].dma_rxbuf_size = &this_mac->mac_base->DMA_RXBUF_SIZE_Q3;
5731     }
5732     else
5733     {
5734         this_mac->queue[0].int_status = &this_mac->emac_base->INT_STATUS;
5735         this_mac->queue[1].int_status = &this_mac->emac_base->INT_STATUS; /* Not Really correct but don't want 0 here... */
5736         this_mac->queue[2].int_status = &this_mac->emac_base->INT_STATUS;
5737         this_mac->queue[3].int_status = &this_mac->emac_base->INT_STATUS;
5738 
5739         this_mac->queue[0].int_mask = &this_mac->emac_base->INT_MASK;
5740         this_mac->queue[1].int_mask = &this_mac->emac_base->INT_MASK;
5741         this_mac->queue[2].int_mask = &this_mac->emac_base->INT_MASK;
5742         this_mac->queue[3].int_mask = &this_mac->emac_base->INT_MASK;
5743 
5744         this_mac->queue[0].int_enable = &this_mac->emac_base->INT_ENABLE;
5745         this_mac->queue[1].int_enable = &this_mac->emac_base->INT_ENABLE;
5746         this_mac->queue[2].int_enable = &this_mac->emac_base->INT_ENABLE;
5747         this_mac->queue[3].int_enable = &this_mac->emac_base->INT_ENABLE;
5748 
5749         this_mac->queue[0].int_disable = &this_mac->emac_base->INT_DISABLE;
5750         this_mac->queue[1].int_disable = &this_mac->emac_base->INT_DISABLE;
5751         this_mac->queue[2].int_disable = &this_mac->emac_base->INT_DISABLE;
5752         this_mac->queue[3].int_disable = &this_mac->emac_base->INT_DISABLE;
5753 
5754         this_mac->queue[0].receive_q_ptr = &this_mac->emac_base->RECEIVE_Q_PTR;
5755         this_mac->queue[1].receive_q_ptr = &this_mac->emac_base->RECEIVE_Q_PTR;
5756         this_mac->queue[2].receive_q_ptr = &this_mac->emac_base->RECEIVE_Q_PTR;
5757         this_mac->queue[3].receive_q_ptr = &this_mac->emac_base->RECEIVE_Q_PTR;
5758 
5759         this_mac->queue[0].transmit_q_ptr = &this_mac->emac_base->TRANSMIT_Q_PTR;
5760         this_mac->queue[1].transmit_q_ptr = &this_mac->emac_base->TRANSMIT_Q_PTR;
5761         this_mac->queue[2].transmit_q_ptr = &this_mac->emac_base->TRANSMIT_Q_PTR;
5762         this_mac->queue[3].transmit_q_ptr = &this_mac->emac_base->TRANSMIT_Q_PTR;
5763 
5764         this_mac->queue[0].dma_rxbuf_size = &this_mac->mac_base->DMA_RXBUF_SIZE_Q1; /* Not really true as this is done differently for queue 0 */
5765         this_mac->queue[1].dma_rxbuf_size = &this_mac->mac_base->DMA_RXBUF_SIZE_Q1; /* Not Really correct but don't want 0 here... */
5766         this_mac->queue[2].dma_rxbuf_size = &this_mac->mac_base->DMA_RXBUF_SIZE_Q2;
5767         this_mac->queue[3].dma_rxbuf_size = &this_mac->mac_base->DMA_RXBUF_SIZE_Q3;
5768     }
5769 #endif /* defined(TARGET_G5_SOC) */
5770 }
5771 
5772 #ifdef __cplusplus
5773 }
5774 #endif
5775 
5776 /******************************** END OF FILE ******************************/
5777