1 /*
2 * Copyright 2008-2012 Freescale Semiconductor Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * * Neither the name of Freescale Semiconductor nor the
12 * names of its contributors may be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 *
16 * ALTERNATIVELY, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL") as published by the Free Software
18 * Foundation, either version 2 of that License or (at your option) any
19 * later version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34 /******************************************************************************
35 @File memac.c
36
37 @Description FM mEMAC driver
38 *//***************************************************************************/
39
40 #include "std_ext.h"
41 #include "string_ext.h"
42 #include "error_ext.h"
43 #include "xx_ext.h"
44 #include "endian_ext.h"
45 #include "debug_ext.h"
46
47 #include "fm_common.h"
48 #include "memac.h"
49
50
51 /*****************************************************************************/
52 /* Internal routines */
53 /*****************************************************************************/
54
55 /* ......................................................................... */
56
GetMacAddrHashCode(uint64_t ethAddr)57 static uint32_t GetMacAddrHashCode(uint64_t ethAddr)
58 {
59 uint64_t mask1, mask2;
60 uint32_t xorVal = 0;
61 uint8_t i, j;
62
63 for (i=0; i<6; i++)
64 {
65 mask1 = ethAddr & (uint64_t)0x01;
66 ethAddr >>= 1;
67
68 for (j=0; j<7; j++)
69 {
70 mask2 = ethAddr & (uint64_t)0x01;
71 mask1 ^= mask2;
72 ethAddr >>= 1;
73 }
74
75 xorVal |= (mask1 << (5-i));
76 }
77
78 return xorVal;
79 }
80
81 /* ......................................................................... */
82
SetupSgmiiInternalPhy(t_Memac * p_Memac,uint8_t phyAddr)83 static void SetupSgmiiInternalPhy(t_Memac *p_Memac, uint8_t phyAddr)
84 {
85 uint16_t tmpReg16;
86 e_EnetMode enetMode;
87
88 /* In case the higher MACs are used (i.e. the MACs that should support 10G),
89 speed=10000 is provided for SGMII ports. Temporary modify enet mode
90 to 1G one, so MII functions can work correctly. */
91 enetMode = p_Memac->enetMode;
92
93 /* SGMII mode + AN enable */
94 tmpReg16 = PHY_SGMII_IF_MODE_AN | PHY_SGMII_IF_MODE_SGMII;
95 if ((p_Memac->enetMode) == e_ENET_MODE_SGMII_2500)
96 tmpReg16 = PHY_SGMII_CR_PHY_RESET | PHY_SGMII_IF_SPEED_GIGABIT | PHY_SGMII_IF_MODE_SGMII;
97
98 p_Memac->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Memac->enetMode), e_ENET_SPEED_1000);
99 MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x14, tmpReg16);
100
101 /* Device ability according to SGMII specification */
102 tmpReg16 = PHY_SGMII_DEV_ABILITY_SGMII;
103 MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x4, tmpReg16);
104
105 /* Adjust link timer for SGMII -
106 According to Cisco SGMII specification the timer should be 1.6 ms.
107 The link_timer register is configured in units of the clock.
108 - When running as 1G SGMII, Serdes clock is 125 MHz, so
109 unit = 1 / (125*10^6 Hz) = 8 ns.
110 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2 * 10^5 = 0x30d40
111 - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
112 unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
113 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5 * 10^5 = 0x7a120.
114 Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
115 we always set up here a value of 2.5 SGMII. */
116 MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x13, 0x0007);
117 MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x12, 0xa120);
118
119 /* Restart AN */
120 tmpReg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
121 MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x0, tmpReg16);
122
123 /* Restore original enet mode */
124 p_Memac->enetMode = enetMode;
125 }
126
127 /* ......................................................................... */
128
SetupSgmiiInternalPhyBaseX(t_Memac * p_Memac,uint8_t phyAddr)129 static void SetupSgmiiInternalPhyBaseX(t_Memac *p_Memac, uint8_t phyAddr)
130 {
131 uint16_t tmpReg16;
132 e_EnetMode enetMode;
133
134 /* In case the higher MACs are used (i.e. the MACs that should support 10G),
135 speed=10000 is provided for SGMII ports. Temporary modify enet mode
136 to 1G one, so MII functions can work correctly. */
137 enetMode = p_Memac->enetMode;
138 p_Memac->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Memac->enetMode), e_ENET_SPEED_1000);
139
140 /* 1000BaseX mode */
141 tmpReg16 = PHY_SGMII_IF_MODE_1000X;
142 MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x14, tmpReg16);
143
144 /* AN Device capability */
145 tmpReg16 = PHY_SGMII_DEV_ABILITY_1000X;
146 MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x4, tmpReg16);
147
148 /* Adjust link timer for SGMII -
149 For Serdes 1000BaseX auto-negotiation the timer should be 10 ms.
150 The link_timer register is configured in units of the clock.
151 - When running as 1G SGMII, Serdes clock is 125 MHz, so
152 unit = 1 / (125*10^6 Hz) = 8 ns.
153 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0
154 - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
155 unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
156 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08.
157 Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
158 we always set up here a value of 2.5 SGMII. */
159 MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x13, 0x002f);
160 MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x12, 0xaf08);
161
162 /* Restart AN */
163 tmpReg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
164 MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x0, tmpReg16);
165
166 /* Restore original enet mode */
167 p_Memac->enetMode = enetMode;
168 }
169
170 /* ......................................................................... */
171
CheckInitParameters(t_Memac * p_Memac)172 static t_Error CheckInitParameters(t_Memac *p_Memac)
173 {
174 e_FmMacType portType;
175
176 portType = ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G);
177
178 #if (FM_MAX_NUM_OF_10G_MACS > 0)
179 if ((portType == e_FM_MAC_10G) && (p_Memac->macId >= FM_MAX_NUM_OF_10G_MACS))
180 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("10G MAC ID must be less than %d", FM_MAX_NUM_OF_10G_MACS));
181 #endif /* (FM_MAX_NUM_OF_10G_MACS > 0) */
182
183 if ((portType == e_FM_MAC_1G) && (p_Memac->macId >= FM_MAX_NUM_OF_1G_MACS))
184 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("1G MAC ID must be less than %d", FM_MAX_NUM_OF_1G_MACS));
185 if (p_Memac->addr == 0)
186 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC must have a valid MAC address"));
187 if (!p_Memac->f_Exception)
188 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Uninitialized f_Exception"));
189 if (!p_Memac->f_Event)
190 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Uninitialized f_Event"));
191 #ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
192 if (!p_Memac->p_MemacDriverParam->no_length_check_enable)
193 RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!"));
194 #endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
195
196 return E_OK;
197 }
198
199 /* ........................................................................... */
200
MemacErrException(t_Handle h_Memac)201 static void MemacErrException(t_Handle h_Memac)
202 {
203 t_Memac *p_Memac = (t_Memac *)h_Memac;
204 uint32_t event, imask;
205
206 event = fman_memac_get_event(p_Memac->p_MemMap, 0xffffffff);
207 imask = fman_memac_get_interrupt_mask(p_Memac->p_MemMap);
208
209 /* Imask include both error and notification/event bits.
210 Leaving only error bits enabled by imask.
211 The imask error bits are shifted by 16 bits offset from
212 their corresponding location in the ievent - hence the >> 16 */
213 event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16);
214
215 fman_memac_ack_event(p_Memac->p_MemMap, event);
216
217 if (event & MEMAC_IEVNT_TS_ECC_ER)
218 p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_TS_FIFO_ECC_ERR);
219 if (event & MEMAC_IEVNT_TX_ECC_ER)
220 p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_1TX_ECC_ER);
221 if (event & MEMAC_IEVNT_RX_ECC_ER)
222 p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_RX_ECC_ER);
223 }
224
MemacException(t_Handle h_Memac)225 static void MemacException(t_Handle h_Memac)
226 {
227 t_Memac *p_Memac = (t_Memac *)h_Memac;
228 uint32_t event, imask;
229
230 event = fman_memac_get_event(p_Memac->p_MemMap, 0xffffffff);
231 imask = fman_memac_get_interrupt_mask(p_Memac->p_MemMap);
232
233 /* Imask include both error and notification/event bits.
234 Leaving only error bits enabled by imask.
235 The imask error bits are shifted by 16 bits offset from
236 their corresponding location in the ievent - hence the >> 16 */
237 event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16);
238
239 fman_memac_ack_event(p_Memac->p_MemMap, event);
240
241 if (event & MEMAC_IEVNT_MGI)
242 p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_MAGIC_PACKET_INDICATION);
243 }
244
245 /* ......................................................................... */
246
FreeInitResources(t_Memac * p_Memac)247 static void FreeInitResources(t_Memac *p_Memac)
248 {
249 e_FmMacType portType;
250
251 portType =
252 ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G);
253
254 if (portType == e_FM_MAC_10G)
255 FmUnregisterIntr(p_Memac->fmMacControllerDriver.h_Fm, e_FM_MOD_10G_MAC, p_Memac->macId, e_FM_INTR_TYPE_ERR);
256 else
257 FmUnregisterIntr(p_Memac->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Memac->macId, e_FM_INTR_TYPE_ERR);
258
259 /* release the driver's group hash table */
260 FreeHashTable(p_Memac->p_MulticastAddrHash);
261 p_Memac->p_MulticastAddrHash = NULL;
262
263 /* release the driver's individual hash table */
264 FreeHashTable(p_Memac->p_UnicastAddrHash);
265 p_Memac->p_UnicastAddrHash = NULL;
266 }
267
268
269 /*****************************************************************************/
270 /* mEMAC API routines */
271 /*****************************************************************************/
272
273 /* ......................................................................... */
274
MemacEnable(t_Handle h_Memac,e_CommMode mode)275 static t_Error MemacEnable(t_Handle h_Memac, e_CommMode mode)
276 {
277 t_Memac *p_Memac = (t_Memac *)h_Memac;
278
279 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
280 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
281
282 fman_memac_enable(p_Memac->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX));
283
284 return E_OK;
285 }
286
287 /* ......................................................................... */
288
MemacDisable(t_Handle h_Memac,e_CommMode mode)289 static t_Error MemacDisable (t_Handle h_Memac, e_CommMode mode)
290 {
291 t_Memac *p_Memac = (t_Memac *)h_Memac;
292
293 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
294 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
295
296 fman_memac_disable(p_Memac->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX));
297
298 return E_OK;
299 }
300
301 /* ......................................................................... */
302
MemacSetPromiscuous(t_Handle h_Memac,bool newVal)303 static t_Error MemacSetPromiscuous(t_Handle h_Memac, bool newVal)
304 {
305 t_Memac *p_Memac = (t_Memac *)h_Memac;
306
307 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
308 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
309
310 fman_memac_set_promiscuous(p_Memac->p_MemMap, newVal);
311
312 return E_OK;
313 }
314
315 /* .............................................................................. */
316
MemacAdjustLink(t_Handle h_Memac,e_EnetSpeed speed,bool fullDuplex)317 static t_Error MemacAdjustLink(t_Handle h_Memac, e_EnetSpeed speed, bool fullDuplex)
318 {
319 t_Memac *p_Memac = (t_Memac *)h_Memac;
320
321 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
322 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
323
324 if ((speed >= e_ENET_SPEED_1000) && (!fullDuplex))
325 RETURN_ERROR(MAJOR, E_CONFLICT,
326 ("Ethernet MAC 1G or 10G does not support half-duplex"));
327
328 fman_memac_adjust_link(p_Memac->p_MemMap,
329 (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_Memac->enetMode),
330 (enum enet_speed)speed,
331 fullDuplex);
332 return E_OK;
333 }
334
335
336 /*****************************************************************************/
337 /* Memac Configs modification functions */
338 /*****************************************************************************/
339
340 /* ......................................................................... */
341
MemacConfigLoopback(t_Handle h_Memac,bool newVal)342 static t_Error MemacConfigLoopback(t_Handle h_Memac, bool newVal)
343 {
344 t_Memac *p_Memac = (t_Memac *)h_Memac;
345
346 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
347 SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
348
349 p_Memac->p_MemacDriverParam->loopback_enable = newVal;
350
351 return E_OK;
352 }
353
354 /* ......................................................................... */
355
MemacConfigWan(t_Handle h_Memac,bool newVal)356 static t_Error MemacConfigWan(t_Handle h_Memac, bool newVal)
357 {
358 t_Memac *p_Memac = (t_Memac *)h_Memac;
359
360 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
361 SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
362
363 p_Memac->p_MemacDriverParam->wan_mode_enable = newVal;
364
365 return E_OK;
366 }
367
368 /* ......................................................................... */
369
MemacConfigMaxFrameLength(t_Handle h_Memac,uint16_t newVal)370 static t_Error MemacConfigMaxFrameLength(t_Handle h_Memac, uint16_t newVal)
371 {
372 t_Memac *p_Memac = (t_Memac *)h_Memac;
373
374 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
375 SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
376
377 p_Memac->p_MemacDriverParam->max_frame_length = newVal;
378
379 return E_OK;
380 }
381
382 /* ......................................................................... */
383
MemacConfigPad(t_Handle h_Memac,bool newVal)384 static t_Error MemacConfigPad(t_Handle h_Memac, bool newVal)
385 {
386 t_Memac *p_Memac = (t_Memac *)h_Memac;
387
388 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
389 SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
390
391 p_Memac->p_MemacDriverParam->pad_enable = newVal;
392
393 return E_OK;
394 }
395
396 /* ......................................................................... */
397
MemacConfigLengthCheck(t_Handle h_Memac,bool newVal)398 static t_Error MemacConfigLengthCheck(t_Handle h_Memac, bool newVal)
399 {
400 t_Memac *p_Memac = (t_Memac *)h_Memac;
401
402 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
403 SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
404
405 p_Memac->p_MemacDriverParam->no_length_check_enable = !newVal;
406
407 return E_OK;
408 }
409
410 /* ......................................................................... */
411
MemacConfigException(t_Handle h_Memac,e_FmMacExceptions exception,bool enable)412 static t_Error MemacConfigException(t_Handle h_Memac, e_FmMacExceptions exception, bool enable)
413 {
414 t_Memac *p_Memac = (t_Memac *)h_Memac;
415 uint32_t bitMask = 0;
416
417 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
418 SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
419
420 GET_EXCEPTION_FLAG(bitMask, exception);
421 if (bitMask)
422 {
423 if (enable)
424 p_Memac->exceptions |= bitMask;
425 else
426 p_Memac->exceptions &= ~bitMask;
427 }
428 else
429 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
430
431 return E_OK;
432 }
433
434 /* ......................................................................... */
435
MemacConfigResetOnInit(t_Handle h_Memac,bool enable)436 static t_Error MemacConfigResetOnInit(t_Handle h_Memac, bool enable)
437 {
438 t_Memac *p_Memac = (t_Memac *)h_Memac;
439
440 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
441 SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
442
443 p_Memac->p_MemacDriverParam->reset_on_init = enable;
444
445 return E_OK;
446 }
447
448
449 /*****************************************************************************/
450 /* Memac Run Time API functions */
451 /*****************************************************************************/
452
453 /* ......................................................................... */
454
MemacSetTxPauseFrames(t_Handle h_Memac,uint8_t priority,uint16_t pauseTime,uint16_t threshTime)455 static t_Error MemacSetTxPauseFrames(t_Handle h_Memac,
456 uint8_t priority,
457 uint16_t pauseTime,
458 uint16_t threshTime)
459 {
460 t_Memac *p_Memac = (t_Memac *)h_Memac;
461
462 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE);
463 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
464
465 if (priority != 0xFF)
466 {
467 bool PortConfigured, PreFetchEnabled;
468
469 if (FmGetTnumAgingPeriod(p_Memac->fmMacControllerDriver.h_Fm) == 0)
470 RETURN_ERROR(MAJOR, E_CONFLICT, ("For PFC operation, TNUM aging must be enabled"));
471
472 FmGetPortPreFetchConfiguration(p_Memac->fmMacControllerDriver.h_Fm,
473 p_Memac->fmMacControllerDriver.macId,
474 &PortConfigured,
475 &PreFetchEnabled);
476
477 if ((ENET_SPEED_FROM_MODE(p_Memac->fmMacControllerDriver.enetMode) == e_ENET_SPEED_1000) && !PortConfigured)
478 DBG(INFO, ("For PFC correct operation, prefetch must be configured on the FM Tx PORT"));
479
480 if ((ENET_SPEED_FROM_MODE(p_Memac->fmMacControllerDriver.enetMode) == e_ENET_SPEED_1000) && PortConfigured && !PreFetchEnabled)
481 DBG(WARNING, ("For PFC correct operation, prefetch must be configured on the FM Tx PORT"));
482 }
483
484 fman_memac_set_tx_pause_frames(p_Memac->p_MemMap, priority, pauseTime, threshTime);
485
486 return E_OK;
487 }
488
489 /* ......................................................................... */
490
MemacSetTxAutoPauseFrames(t_Handle h_Memac,uint16_t pauseTime)491 static t_Error MemacSetTxAutoPauseFrames(t_Handle h_Memac,
492 uint16_t pauseTime)
493 {
494 return MemacSetTxPauseFrames(h_Memac, FM_MAC_NO_PFC, pauseTime, 0);
495 }
496
497 /* ......................................................................... */
498
MemacSetRxIgnorePauseFrames(t_Handle h_Memac,bool en)499 static t_Error MemacSetRxIgnorePauseFrames(t_Handle h_Memac, bool en)
500 {
501 t_Memac *p_Memac = (t_Memac *)h_Memac;
502
503 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE);
504 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
505
506 fman_memac_set_rx_ignore_pause_frames(p_Memac->p_MemMap, en);
507
508 return E_OK;
509 }
510
511 /* ......................................................................... */
512
MemacSetWakeOnLan(t_Handle h_Memac,bool en)513 static t_Error MemacSetWakeOnLan(t_Handle h_Memac, bool en)
514 {
515 t_Memac *p_Memac = (t_Memac *)h_Memac;
516
517 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE);
518 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
519
520 fman_memac_set_wol(p_Memac->p_MemMap, en);
521
522 return E_OK;
523 }
524
525 /* .............................................................................. */
526
MemacEnable1588TimeStamp(t_Handle h_Memac)527 static t_Error MemacEnable1588TimeStamp(t_Handle h_Memac)
528 {
529 t_Memac *p_Memac = (t_Memac *)h_Memac;
530
531 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
532 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
533 UNUSED(p_Memac);
534 DBG(WARNING, ("mEMAC has 1588 always enabled!"));
535
536 return E_OK;
537 }
538
539 /* Counters handling */
540 /* ......................................................................... */
541
MemacGetStatistics(t_Handle h_Memac,t_FmMacStatistics * p_Statistics)542 static t_Error MemacGetStatistics(t_Handle h_Memac, t_FmMacStatistics *p_Statistics)
543 {
544 t_Memac *p_Memac = (t_Memac *)h_Memac;
545
546 SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
547 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
548 SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER);
549
550 p_Statistics->eStatPkts64 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R64);
551 p_Statistics->eStatPkts65to127 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R127);
552 p_Statistics->eStatPkts128to255 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R255);
553 p_Statistics->eStatPkts256to511 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R511);
554 p_Statistics->eStatPkts512to1023 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1023);
555 p_Statistics->eStatPkts1024to1518 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1518);
556 p_Statistics->eStatPkts1519to1522 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1519X);
557 /* */
558 p_Statistics->eStatFragments = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RFRG);
559 p_Statistics->eStatJabbers = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RJBR);
560
561 p_Statistics->eStatsDropEvents = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RDRP);
562 p_Statistics->eStatCRCAlignErrors = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RALN);
563
564 p_Statistics->eStatUndersizePkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TUND);
565 p_Statistics->eStatOversizePkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_ROVR);
566 /* Pause */
567 p_Statistics->reStatPause = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RXPF);
568 p_Statistics->teStatPause = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TXPF);
569
570 /* MIB II */
571 p_Statistics->ifInOctets = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_ROCT);
572 p_Statistics->ifInUcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RUCA);
573 p_Statistics->ifInMcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RMCA);
574 p_Statistics->ifInBcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RBCA);
575 p_Statistics->ifInPkts = p_Statistics->ifInUcastPkts
576 + p_Statistics->ifInMcastPkts
577 + p_Statistics->ifInBcastPkts;
578 p_Statistics->ifInDiscards = 0;
579 p_Statistics->ifInErrors = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RERR);
580
581 p_Statistics->ifOutOctets = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TOCT);
582 p_Statistics->ifOutUcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TUCA);
583 p_Statistics->ifOutMcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TMCA);
584 p_Statistics->ifOutBcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TBCA);
585 p_Statistics->ifOutPkts = p_Statistics->ifOutUcastPkts
586 + p_Statistics->ifOutMcastPkts
587 + p_Statistics->ifOutBcastPkts;
588 p_Statistics->ifOutDiscards = 0;
589 p_Statistics->ifOutErrors = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TERR);
590
591 return E_OK;
592 }
593
594 /* ......................................................................... */
595
MemacModifyMacAddress(t_Handle h_Memac,t_EnetAddr * p_EnetAddr)596 static t_Error MemacModifyMacAddress (t_Handle h_Memac, t_EnetAddr *p_EnetAddr)
597 {
598 t_Memac *p_Memac = (t_Memac *)h_Memac;
599
600 SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
601 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
602
603 fman_memac_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t *)(*p_EnetAddr), 0);
604
605 return E_OK;
606 }
607
608 /* ......................................................................... */
609
MemacResetCounters(t_Handle h_Memac)610 static t_Error MemacResetCounters (t_Handle h_Memac)
611 {
612 t_Memac *p_Memac = (t_Memac *)h_Memac;
613
614 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
615 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
616
617 fman_memac_reset_stat(p_Memac->p_MemMap);
618
619 return E_OK;
620 }
621
622 /* ......................................................................... */
623
MemacAddExactMatchMacAddress(t_Handle h_Memac,t_EnetAddr * p_EthAddr)624 static t_Error MemacAddExactMatchMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
625 {
626 t_Memac *p_Memac = (t_Memac *) h_Memac;
627 uint64_t ethAddr;
628 uint8_t paddrNum;
629
630 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
631 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
632
633 ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
634
635 if (ethAddr & GROUP_ADDRESS)
636 /* Multicast address has no effect in PADDR */
637 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address"));
638
639 /* Make sure no PADDR contains this address */
640 for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++)
641 if (p_Memac->indAddrRegUsed[paddrNum])
642 if (p_Memac->paddr[paddrNum] == ethAddr)
643 RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
644
645 /* Find first unused PADDR */
646 for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++)
647 if (!(p_Memac->indAddrRegUsed[paddrNum]))
648 {
649 /* mark this PADDR as used */
650 p_Memac->indAddrRegUsed[paddrNum] = TRUE;
651 /* store address */
652 p_Memac->paddr[paddrNum] = ethAddr;
653
654 /* put in hardware */
655 fman_memac_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t*)(*p_EthAddr), paddrNum);
656 p_Memac->numOfIndAddrInRegs++;
657
658 return E_OK;
659 }
660
661 /* No free PADDR */
662 RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
663 }
664
665 /* ......................................................................... */
666
MemacDelExactMatchMacAddress(t_Handle h_Memac,t_EnetAddr * p_EthAddr)667 static t_Error MemacDelExactMatchMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
668 {
669 t_Memac *p_Memac = (t_Memac *) h_Memac;
670 uint64_t ethAddr;
671 uint8_t paddrNum;
672
673 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
674 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
675
676 ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
677
678 /* Find used PADDR containing this address */
679 for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++)
680 {
681 if ((p_Memac->indAddrRegUsed[paddrNum]) &&
682 (p_Memac->paddr[paddrNum] == ethAddr))
683 {
684 /* mark this PADDR as not used */
685 p_Memac->indAddrRegUsed[paddrNum] = FALSE;
686 /* clear in hardware */
687 fman_memac_clear_addr_in_paddr(p_Memac->p_MemMap, paddrNum);
688 p_Memac->numOfIndAddrInRegs--;
689
690 return E_OK;
691 }
692 }
693
694 RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG);
695 }
696
697 /* ......................................................................... */
698
MemacGetId(t_Handle h_Memac,uint32_t * macId)699 static t_Error MemacGetId(t_Handle h_Memac, uint32_t *macId)
700 {
701 t_Memac *p_Memac = (t_Memac *)h_Memac;
702
703 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
704 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
705
706 *macId = p_Memac->macId;
707
708 return E_OK;
709 }
710
711 /* ......................................................................... */
712
713
MemacAddHashMacAddress(t_Handle h_Memac,t_EnetAddr * p_EthAddr)714 static t_Error MemacAddHashMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
715 {
716 t_Memac *p_Memac = (t_Memac *)h_Memac;
717 t_EthHashEntry *p_HashEntry;
718 uint32_t hash;
719 uint64_t ethAddr;
720
721 SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
722 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
723
724 ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
725
726 if (!(ethAddr & GROUP_ADDRESS))
727 /* Unicast addresses not supported in hash */
728 RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unicast Address"));
729
730 hash = GetMacAddrHashCode(ethAddr) & HASH_CTRL_ADDR_MASK;
731
732 /* Create element to be added to the driver hash table */
733 p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry));
734 p_HashEntry->addr = ethAddr;
735 INIT_LIST(&p_HashEntry->node);
736
737 LIST_AddToTail(&(p_HashEntry->node), &(p_Memac->p_MulticastAddrHash->p_Lsts[hash]));
738 fman_memac_set_hash_table(p_Memac->p_MemMap, (hash | HASH_CTRL_MCAST_EN));
739
740 return E_OK;
741 }
742
743 /* ......................................................................... */
744
MemacDelHashMacAddress(t_Handle h_Memac,t_EnetAddr * p_EthAddr)745 static t_Error MemacDelHashMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
746 {
747 t_Memac *p_Memac = (t_Memac *)h_Memac;
748 t_EthHashEntry *p_HashEntry = NULL;
749 t_List *p_Pos;
750 uint32_t hash;
751 uint64_t ethAddr;
752
753 SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
754 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
755
756 ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
757
758 hash = GetMacAddrHashCode(ethAddr) & HASH_CTRL_ADDR_MASK;
759
760 LIST_FOR_EACH(p_Pos, &(p_Memac->p_MulticastAddrHash->p_Lsts[hash]))
761 {
762 p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);
763 if (p_HashEntry->addr == ethAddr)
764 {
765 LIST_DelAndInit(&p_HashEntry->node);
766 XX_Free(p_HashEntry);
767 break;
768 }
769 }
770 if (LIST_IsEmpty(&p_Memac->p_MulticastAddrHash->p_Lsts[hash]))
771 fman_memac_set_hash_table(p_Memac->p_MemMap, (hash & ~HASH_CTRL_MCAST_EN));
772
773 return E_OK;
774 }
775
776
777 /* ......................................................................... */
778
MemacSetException(t_Handle h_Memac,e_FmMacExceptions exception,bool enable)779 static t_Error MemacSetException(t_Handle h_Memac, e_FmMacExceptions exception, bool enable)
780 {
781 t_Memac *p_Memac = (t_Memac *)h_Memac;
782 uint32_t bitMask = 0;
783
784 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
785 SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
786
787 GET_EXCEPTION_FLAG(bitMask, exception);
788 if (bitMask)
789 {
790 if (enable)
791 p_Memac->exceptions |= bitMask;
792 else
793 p_Memac->exceptions &= ~bitMask;
794 }
795 else
796 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
797
798 fman_memac_set_exception(p_Memac->p_MemMap, bitMask, enable);
799
800 return E_OK;
801 }
802
803 /* ......................................................................... */
804
MemacGetMaxFrameLength(t_Handle h_Memac)805 static uint16_t MemacGetMaxFrameLength(t_Handle h_Memac)
806 {
807 t_Memac *p_Memac = (t_Memac *)h_Memac;
808
809 SANITY_CHECK_RETURN_VALUE(p_Memac, E_INVALID_HANDLE, 0);
810 SANITY_CHECK_RETURN_VALUE(!p_Memac->p_MemacDriverParam, E_INVALID_STATE, 0);
811
812 return fman_memac_get_max_frame_len(p_Memac->p_MemMap);
813 }
814
MemacInitInternalPhy(t_Handle h_Memac)815 static t_Error MemacInitInternalPhy(t_Handle h_Memac)
816 {
817 t_Memac *p_Memac = (t_Memac *)h_Memac;
818 uint8_t i, phyAddr;
819
820 if (ENET_INTERFACE_FROM_MODE(p_Memac->enetMode) == e_ENET_IF_SGMII)
821 {
822 /* Configure internal SGMII PHY */
823 if (p_Memac->enetMode & ENET_IF_SGMII_BASEX)
824 SetupSgmiiInternalPhyBaseX(p_Memac, PHY_MDIO_ADDR);
825 else
826 SetupSgmiiInternalPhy(p_Memac, PHY_MDIO_ADDR);
827 }
828 else if (ENET_INTERFACE_FROM_MODE(p_Memac->enetMode) == e_ENET_IF_QSGMII)
829 {
830 /* Configure 4 internal SGMII PHYs */
831 for (i = 0; i < 4; i++)
832 {
833 /* QSGMII PHY address occupies 3 upper bits of 5-bit
834 phyAddress; the lower 2 bits are used to extend
835 register address space and access each one of 4
836 ports inside QSGMII. */
837 phyAddr = (uint8_t)((PHY_MDIO_ADDR << 2) | i);
838 if (p_Memac->enetMode & ENET_IF_SGMII_BASEX)
839 SetupSgmiiInternalPhyBaseX(p_Memac, phyAddr);
840 else
841 SetupSgmiiInternalPhy(p_Memac, phyAddr);
842 }
843 }
844 return E_OK;
845 }
846
847 /*****************************************************************************/
848 /* mEMAC Init & Free API */
849 /*****************************************************************************/
850
851 /* ......................................................................... */
852 void *g_MemacRegs;
MemacInit(t_Handle h_Memac)853 static t_Error MemacInit(t_Handle h_Memac)
854 {
855 t_Memac *p_Memac = (t_Memac *)h_Memac;
856 struct memac_cfg *p_MemacDriverParam;
857 enum enet_interface enet_interface;
858 enum enet_speed enet_speed;
859 t_EnetAddr ethAddr;
860 e_FmMacType portType;
861 t_Error err;
862 bool slow_10g_if = FALSE;
863 if (p_Memac->macId == 3) /* This is a quick WA */
864 g_MemacRegs = p_Memac->p_MemMap;
865
866 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
867 SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
868 SANITY_CHECK_RETURN_ERROR(p_Memac->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE);
869
870 FM_GetRevision(p_Memac->fmMacControllerDriver.h_Fm, &p_Memac->fmMacControllerDriver.fmRevInfo);
871 if (p_Memac->fmMacControllerDriver.fmRevInfo.majorRev == 6 &&
872 p_Memac->fmMacControllerDriver.fmRevInfo.minorRev == 4)
873 slow_10g_if = TRUE;
874
875 CHECK_INIT_PARAMETERS(p_Memac, CheckInitParameters);
876
877 p_MemacDriverParam = p_Memac->p_MemacDriverParam;
878
879 portType =
880 ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G);
881
882 /* First, reset the MAC if desired. */
883 if (p_MemacDriverParam->reset_on_init)
884 fman_memac_reset(p_Memac->p_MemMap);
885
886 /* MAC Address */
887 MAKE_ENET_ADDR_FROM_UINT64(p_Memac->addr, ethAddr);
888 fman_memac_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t*)ethAddr, 0);
889
890 enet_interface = (enum enet_interface) ENET_INTERFACE_FROM_MODE(p_Memac->enetMode);
891 enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Memac->enetMode);
892
893 fman_memac_init(p_Memac->p_MemMap,
894 p_Memac->p_MemacDriverParam,
895 enet_interface,
896 enet_speed,
897 slow_10g_if,
898 p_Memac->exceptions);
899
900 #ifdef FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320
901 {
902 uint32_t tmpReg = 0;
903
904 FM_GetRevision(p_Memac->fmMacControllerDriver.h_Fm, &p_Memac->fmMacControllerDriver.fmRevInfo);
905 /* check the FMAN version - the bug exists only in rev1 */
906 if ((p_Memac->fmMacControllerDriver.fmRevInfo.majorRev == 6) &&
907 (p_Memac->fmMacControllerDriver.fmRevInfo.minorRev == 0))
908 {
909 /* MAC strips CRC from received frames - this workaround should
910 decrease the likelihood of bug appearance
911 */
912 tmpReg = GET_UINT32(p_Memac->p_MemMap->command_config);
913 tmpReg &= ~CMD_CFG_CRC_FWD;
914 WRITE_UINT32(p_Memac->p_MemMap->command_config, tmpReg);
915 /* DBG(WARNING, ("mEMAC strips CRC from received frames as part of A006320 errata workaround"));*/
916 }
917 }
918 #endif /* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 */
919
920 MemacInitInternalPhy(h_Memac);
921
922 /* Max Frame Length */
923 err = FmSetMacMaxFrame(p_Memac->fmMacControllerDriver.h_Fm,
924 portType,
925 p_Memac->fmMacControllerDriver.macId,
926 p_MemacDriverParam->max_frame_length);
927 if (err)
928 RETURN_ERROR(MAJOR, err, ("settings Mac max frame length is FAILED"));
929
930 p_Memac->p_MulticastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
931 if (!p_Memac->p_MulticastAddrHash)
932 {
933 FreeInitResources(p_Memac);
934 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED"));
935 }
936
937 p_Memac->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
938 if (!p_Memac->p_UnicastAddrHash)
939 {
940 FreeInitResources(p_Memac);
941 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED"));
942 }
943
944 FmRegisterIntr(p_Memac->fmMacControllerDriver.h_Fm,
945 (portType == e_FM_MAC_10G) ? e_FM_MOD_10G_MAC : e_FM_MOD_1G_MAC,
946 p_Memac->macId,
947 e_FM_INTR_TYPE_ERR,
948 MemacErrException,
949 p_Memac);
950
951 FmRegisterIntr(p_Memac->fmMacControllerDriver.h_Fm,
952 (portType == e_FM_MAC_10G) ? e_FM_MOD_10G_MAC : e_FM_MOD_1G_MAC,
953 p_Memac->macId,
954 e_FM_INTR_TYPE_NORMAL,
955 MemacException,
956 p_Memac);
957
958 XX_Free(p_MemacDriverParam);
959 p_Memac->p_MemacDriverParam = NULL;
960
961 return E_OK;
962 }
963
964 /* ......................................................................... */
965
MemacFree(t_Handle h_Memac)966 static t_Error MemacFree(t_Handle h_Memac)
967 {
968 t_Memac *p_Memac = (t_Memac *)h_Memac;
969
970 SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
971
972 if (p_Memac->p_MemacDriverParam)
973 {
974 /* Called after config */
975 XX_Free(p_Memac->p_MemacDriverParam);
976 p_Memac->p_MemacDriverParam = NULL;
977 }
978 else
979 /* Called after init */
980 FreeInitResources(p_Memac);
981
982 XX_Free(p_Memac);
983
984 return E_OK;
985 }
986
987 /* ......................................................................... */
988
InitFmMacControllerDriver(t_FmMacControllerDriver * p_FmMacControllerDriver)989 static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver)
990 {
991 p_FmMacControllerDriver->f_FM_MAC_Init = MemacInit;
992 p_FmMacControllerDriver->f_FM_MAC_Free = MemacFree;
993
994 p_FmMacControllerDriver->f_FM_MAC_SetStatistics = NULL;
995 p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = MemacConfigLoopback;
996 p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = MemacConfigMaxFrameLength;
997
998 p_FmMacControllerDriver->f_FM_MAC_ConfigWan = MemacConfigWan;
999
1000 p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = MemacConfigPad;
1001 p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = NULL; /* half-duplex is detected automatically */
1002 p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = MemacConfigLengthCheck;
1003
1004 p_FmMacControllerDriver->f_FM_MAC_ConfigException = MemacConfigException;
1005 p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = MemacConfigResetOnInit;
1006
1007 p_FmMacControllerDriver->f_FM_MAC_SetException = MemacSetException;
1008
1009 p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = MemacEnable1588TimeStamp; /* always enabled */
1010 p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = NULL;
1011
1012 p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = MemacSetPromiscuous;
1013 p_FmMacControllerDriver->f_FM_MAC_AdjustLink = MemacAdjustLink;
1014 p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = NULL;
1015
1016 p_FmMacControllerDriver->f_FM_MAC_Enable = MemacEnable;
1017 p_FmMacControllerDriver->f_FM_MAC_Disable = MemacDisable;
1018 p_FmMacControllerDriver->f_FM_MAC_Resume = MemacInitInternalPhy;
1019
1020 p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = MemacSetTxAutoPauseFrames;
1021 p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = MemacSetTxPauseFrames;
1022 p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = MemacSetRxIgnorePauseFrames;
1023
1024 p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan = MemacSetWakeOnLan;
1025
1026 p_FmMacControllerDriver->f_FM_MAC_ResetCounters = MemacResetCounters;
1027 p_FmMacControllerDriver->f_FM_MAC_GetStatistics = MemacGetStatistics;
1028
1029 p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = MemacModifyMacAddress;
1030 p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = MemacAddHashMacAddress;
1031 p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = MemacDelHashMacAddress;
1032 p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = MemacAddExactMatchMacAddress;
1033 p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = MemacDelExactMatchMacAddress;
1034 p_FmMacControllerDriver->f_FM_MAC_GetId = MemacGetId;
1035 p_FmMacControllerDriver->f_FM_MAC_GetVersion = NULL;
1036 p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = MemacGetMaxFrameLength;
1037
1038 p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = MEMAC_MII_WritePhyReg;
1039 p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = MEMAC_MII_ReadPhyReg;
1040 }
1041
1042
1043 /*****************************************************************************/
1044 /* mEMAC Config Main Entry */
1045 /*****************************************************************************/
1046
1047 /* ......................................................................... */
1048
MEMAC_Config(t_FmMacParams * p_FmMacParam)1049 t_Handle MEMAC_Config(t_FmMacParams *p_FmMacParam)
1050 {
1051 t_Memac *p_Memac;
1052 struct memac_cfg *p_MemacDriverParam;
1053 uintptr_t baseAddr;
1054
1055 SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL);
1056
1057 baseAddr = p_FmMacParam->baseAddr;
1058 /* Allocate memory for the mEMAC data structure */
1059 p_Memac = (t_Memac *)XX_Malloc(sizeof(t_Memac));
1060 if (!p_Memac)
1061 {
1062 REPORT_ERROR(MAJOR, E_NO_MEMORY, ("mEMAC driver structure"));
1063 return NULL;
1064 }
1065 memset(p_Memac, 0, sizeof(t_Memac));
1066 InitFmMacControllerDriver(&p_Memac->fmMacControllerDriver);
1067
1068 /* Allocate memory for the mEMAC driver parameters data structure */
1069 p_MemacDriverParam = (struct memac_cfg *)XX_Malloc(sizeof(struct memac_cfg));
1070 if (!p_MemacDriverParam)
1071 {
1072 REPORT_ERROR(MAJOR, E_NO_MEMORY, ("mEMAC driver parameters"));
1073 XX_Free(p_Memac);
1074 return NULL;
1075 }
1076 memset(p_MemacDriverParam, 0, sizeof(struct memac_cfg));
1077
1078 /* Plant parameter structure pointer */
1079 p_Memac->p_MemacDriverParam = p_MemacDriverParam;
1080
1081 fman_memac_defconfig(p_MemacDriverParam);
1082
1083 p_Memac->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr);
1084
1085 p_Memac->p_MemMap = (struct memac_regs *)UINT_TO_PTR(baseAddr);
1086 p_Memac->p_MiiMemMap = (struct memac_mii_access_mem_map*)UINT_TO_PTR(baseAddr + MEMAC_TO_MII_OFFSET);
1087
1088 p_Memac->enetMode = p_FmMacParam->enetMode;
1089 p_Memac->macId = p_FmMacParam->macId;
1090 p_Memac->exceptions = MEMAC_default_exceptions;
1091 p_Memac->f_Exception = p_FmMacParam->f_Exception;
1092 p_Memac->f_Event = p_FmMacParam->f_Event;
1093 p_Memac->h_App = p_FmMacParam->h_App;
1094
1095 return p_Memac;
1096 }
1097