1 /*
2 * Copyright (c) 2007-2008, Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Advanced Micro Devices, Inc. nor the names
16 * of its contributors may be used to endorse or promote products
17 * derived from this software without specific prior written
18 * permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Some portions copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
35 *
36 * Xilinx, Inc.
37 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
38 * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
39 * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
40 * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
41 * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
42 * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
43 * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
44 * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
45 * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
46 * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
47 * AND FITNESS FOR A PARTICULAR PURPOSE.
48 *
49 */
50
51 /* Standard includes. */
52 #include <stdint.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55
56 /* FreeRTOS includes. */
57 #include "FreeRTOS.h"
58 #include "task.h"
59 #include "queue.h"
60 #include "semphr.h"
61
62 /* FreeRTOS+TCP includes. */
63 #include "FreeRTOS_IP.h"
64 #include "FreeRTOS_Sockets.h"
65 #include "FreeRTOS_IP_Private.h"
66 #include "FreeRTOS_Routing.h"
67 #include "NetworkBufferManagement.h"
68
69 #include "Zynq/x_emacpsif.h"
70 #include "xparameters_ps.h"
71 #include "xparameters.h"
72
73 #define ETH0_PHY_ADDRESS ( 1 ) /* Hardwired in WFI PCB */
74 #define ETH1_PHY_ADDRESS ( 2 ) /* Hardwired in WFI PCB */
75 int phy_detected[ 2 ] = { ETH0_PHY_ADDRESS, ETH1_PHY_ADDRESS };
76
77
78 /* Advertisement control register. */
79 #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
80 #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
81 #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
82 #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
83
84 #define ADVERTISE_100_AND_10 \
85 ( ADVERTISE_10FULL | ADVERTISE_100FULL | \
86 ADVERTISE_10HALF | ADVERTISE_100HALF )
87 #define ADVERTISE_100 ( ADVERTISE_100FULL | ADVERTISE_100HALF )
88 #define ADVERTISE_10 ( ADVERTISE_10FULL | ADVERTISE_10HALF )
89
90 #define ADVERTISE_1000 0x0300
91
92
93 #define IEEE_CONTROL_REG_OFFSET 0
94 #define IEEE_STATUS_REG_OFFSET 1
95 #define IEEE_AUTONEGO_ADVERTISE_REG 4
96 #define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5
97 #define IEEE_1000_ADVERTISE_REG_OFFSET 9
98 #define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10
99 #define IEEE_COPPER_SPECIFIC_CONTROL_REG 16
100 #define IEEE_SPECIFIC_STATUS_REG 17
101 #define IEEE_COPPER_SPECIFIC_STATUS_REG_2 19
102 #define IEEE_CONTROL_REG_MAC 21
103 #define IEEE_PAGE_ADDRESS_REGISTER 22
104
105
106 #define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040
107 #define IEEE_CTRL_LINKSPEED_MASK 0x0040
108 #define IEEE_CTRL_LINKSPEED_1000M 0x0040
109 #define IEEE_CTRL_LINKSPEED_100M 0x2000
110 #define IEEE_CTRL_LINKSPEED_10M 0x0000
111 #define IEEE_CTRL_RESET_MASK 0x8000
112 #define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000
113 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
114 #define IEEE_CTRL_RESET 0x9140
115 #define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF
116 #endif
117 #define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008
118 #define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020
119 #define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200
120 #define IEEE_STAT_1GBPS_EXTENSIONS 0x0100
121 #define IEEE_AN1_ABILITY_MASK 0x1FE0
122 #define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00
123 #define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380
124 #define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060
125 #define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK 0x0030
126
127 #define IEEE_ASYMMETRIC_PAUSE_MASK 0x0800
128 #define IEEE_PAUSE_MASK 0x0400
129 #define IEEE_AUTONEG_ERROR_MASK 0x8000
130
131 #define PHY_DETECT_REG 1
132 #define PHY_DETECT_MASK 0x1808
133
134 #define XEMACPS_GMII2RGMII_SPEED1000_FD 0x140
135 #define XEMACPS_GMII2RGMII_SPEED100_FD 0x2100
136 #define XEMACPS_GMII2RGMII_SPEED10_FD 0x100
137 #define XEMACPS_GMII2RGMII_REG_NUM 0x10
138
139 /* Frequency setting */
140 #define SLCR_LOCK_ADDR ( XPS_SYS_CTRL_BASEADDR + 0x4 )
141 #define SLCR_UNLOCK_ADDR ( XPS_SYS_CTRL_BASEADDR + 0x8 )
142 #define SLCR_GEM0_CLK_CTRL_ADDR ( XPS_SYS_CTRL_BASEADDR + 0x140 )
143 #define SLCR_GEM1_CLK_CTRL_ADDR ( XPS_SYS_CTRL_BASEADDR + 0x144 )
144 #ifdef PEEP
145 #define SLCR_GEM_10M_CLK_CTRL_VALUE 0x00103031
146 #define SLCR_GEM_100M_CLK_CTRL_VALUE 0x00103001
147 #define SLCR_GEM_1G_CLK_CTRL_VALUE 0x00103011
148 #endif
149 #define SLCR_LOCK_KEY_VALUE 0x767B
150 #define SLCR_UNLOCK_KEY_VALUE 0xDF0D
151 #define SLCR_ADDR_GEM_RST_CTRL ( XPS_SYS_CTRL_BASEADDR + 0x214 )
152 #define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF
153
154 #define EMAC0_BASE_ADDRESS 0xE000B000
155 #define EMAC1_BASE_ADDRESS 0xE000C000
156
157 #define PHY_ADDRESS_COUNT 32
158
159 #define MINIMUM_SLEEP_TIME 2
160
161
detect_phy(XEmacPs * xemacpsp)162 static int detect_phy( XEmacPs * xemacpsp )
163 {
164 u16 id_lower, id_upper;
165 u32 phy_addr;
166
167 for( phy_addr = 0; phy_addr < PHY_ADDRESS_COUNT; phy_addr++ )
168 {
169 XEmacPs_PhyRead( xemacpsp, phy_addr, PHY_DETECT_REG, &id_lower );
170
171 if( ( id_lower != 0xFFFF ) &&
172 ( ( id_lower & PHY_DETECT_MASK ) == PHY_DETECT_MASK ) )
173 {
174 /* Found a valid PHY address */
175 FreeRTOS_printf( ( "XEmacPs detect_phy: PHY detected at address %d.\n", ( unsigned ) phy_addr ) );
176 phy_detected[ xemacpsp->Config.DeviceId ] = phy_addr;
177 return phy_addr;
178 }
179 }
180
181 FreeRTOS_printf( ( "XEmacPs detect_phy: No PHY detected. Assuming a PHY at address 0\n" ) );
182
183 /* default to zero */
184 return 0;
185 }
186
187 #ifdef PEEP
get_IEEE_phy_speed(XEmacPs * xemacpsp)188 unsigned get_IEEE_phy_speed( XEmacPs * xemacpsp )
189 {
190 u16 control;
191 u16 status;
192 u16 partner_capabilities;
193 u16 partner_capabilities_1000;
194 u16 phylinkspeed;
195 u32 phy_addr = detect_phy( xemacpsp );
196
197 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
198 ADVERTISE_1000 );
199 /* Advertise PHY speed of 100 and 10 Mbps */
200 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
201 ADVERTISE_100_AND_10 );
202
203 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
204 &control );
205 control |= ( IEEE_CTRL_AUTONEGOTIATE_ENABLE |
206 IEEE_STAT_AUTONEGOTIATE_RESTART );
207
208 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );
209
210 /* Read PHY control and status registers is successful. */
211 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
212 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status );
213
214 if( ( control & IEEE_CTRL_AUTONEGOTIATE_ENABLE ) && ( status &
215 IEEE_STAT_AUTONEGOTIATE_CAPABLE ) )
216 {
217 while( !( status & IEEE_STAT_AUTONEGOTIATE_COMPLETE ) )
218 {
219 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
220 &status );
221 }
222
223 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,
224 &partner_capabilities );
225
226 if( status & IEEE_STAT_1GBPS_EXTENSIONS )
227 {
228 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,
229 &partner_capabilities_1000 );
230
231 if( partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS )
232 {
233 return 1000;
234 }
235 }
236
237 if( partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS )
238 {
239 return 100;
240 }
241
242 if( partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS )
243 {
244 return 10;
245 }
246
247 FreeRTOS_printf( ( "%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\n",
248 __FUNCTION__ ) );
249 return 10;
250 }
251 else
252 {
253 /* Update TEMAC speed accordingly */
254 if( status & IEEE_STAT_1GBPS_EXTENSIONS )
255 {
256 /* Get commanded link speed */
257 phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;
258
259 switch( phylinkspeed )
260 {
261 case ( IEEE_CTRL_LINKSPEED_1000M ):
262 return 1000;
263
264 case ( IEEE_CTRL_LINKSPEED_100M ):
265 return 100;
266
267 case ( IEEE_CTRL_LINKSPEED_10M ):
268 return 10;
269
270 default:
271 FreeRTOS_printf( ( "%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\n",
272 __FUNCTION__, phylinkspeed ) );
273 return 10;
274 }
275 }
276 else
277 {
278 return ( control & IEEE_CTRL_LINKSPEED_MASK ) ? 100 : 10;
279 }
280 }
281 }
282
283 #else /* Zynq */
get_IEEE_phy_speed(XEmacPs * xemacpsp)284 unsigned get_IEEE_phy_speed( XEmacPs * xemacpsp )
285 {
286 u16 temp;
287 u16 control;
288 u16 status;
289 u16 partner_capabilities;
290
291 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
292 u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;
293 #else
294 /* PHY addresses hardcoded ETH0=1 and ETH1=2. */
295 u32 phy_addr = detect_phy( xemacpsp );
296 #endif
297 FreeRTOS_printf( ( "Start PHY autonegotiation \n" ) );
298
299 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
300 #else
301 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2 );
302 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control );
303 control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
304 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control );
305
306 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0 );
307
308 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control );
309 control |= IEEE_ASYMMETRIC_PAUSE_MASK;
310 control |= IEEE_PAUSE_MASK;
311 control |= ADVERTISE_100;
312 control |= ADVERTISE_10;
313 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control );
314
315 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
316 &control );
317 control |= ADVERTISE_1000;
318 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
319 control );
320
321 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0 );
322 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
323 &control );
324 control |= ( 7 << 12 ); /* max number of gigabit attempts */
325 control |= ( 1 << 11 ); /* enable downshift */
326 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
327 control );
328 #endif /* if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 */
329 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
330 control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
331 control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
332 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
333 control &= IEEE_CTRL_ISOLATE_DISABLE;
334 #endif
335
336 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );
337
338
339 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
340 #else
341 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
342 control |= IEEE_CTRL_RESET_MASK;
343 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );
344
345 while( 1 )
346 {
347 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
348
349 if( control & IEEE_CTRL_RESET_MASK )
350 {
351 continue;
352 }
353 else
354 {
355 break;
356 }
357 }
358 #endif /* if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 */
359 FreeRTOS_printf( ( "Waiting for PHY to complete autonegotiation.\n" ) );
360
361 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status );
362
363 while( !( status & IEEE_STAT_AUTONEGOTIATE_COMPLETE ) )
364 {
365 vTaskDelay( MINIMUM_SLEEP_TIME );
366 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
367 #else
368 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,
369 &temp );
370
371 if( temp & IEEE_AUTONEG_ERROR_MASK )
372 {
373 FreeRTOS_printf( ( "Auto negotiation error \n" ) );
374 }
375 #endif
376 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
377 &status );
378 }
379
380 FreeRTOS_printf( ( "autonegotiation complete \n" ) );
381
382 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
383 #else
384 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities );
385 #endif
386
387 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
388 FreeRTOS_printf( ( "Waiting for Link to be up; Polling for SGMII core Reg \n" ) );
389 XEmacPs_PhyRead( xemacpsp, phy_addr, 5, &temp );
390
391 while( !( temp & 0x8000 ) )
392 {
393 XEmacPs_PhyRead( xemacpsp, phy_addr, 5, &temp );
394 }
395
396 if( ( temp & 0x0C00 ) == 0x0800 )
397 {
398 XEmacPs_PhyRead( xemacpsp, phy_addr, 0, &temp );
399 return 1000;
400 }
401 else if( ( temp & 0x0C00 ) == 0x0400 )
402 {
403 XEmacPs_PhyRead( xemacpsp, phy_addr, 0, &temp );
404 return 100;
405 }
406 else if( ( temp & 0x0C00 ) == 0x0000 )
407 {
408 XEmacPs_PhyRead( xemacpsp, phy_addr, 0, &temp );
409 return 10;
410 }
411 else
412 {
413 FreeRTOS_printf( ( "get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\n" ) );
414 XEmacPs_PhyRead( xemacpsp, phy_addr, 0, &temp );
415 XEmacPs_PhyWrite( xemacpsp, phy_addr, 0, 0x0100 );
416 return 10;
417 }
418 #else /* if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 */
419 if( ( ( partner_capabilities >> 14 ) & 3 ) == 2 ) /* 1000Mbps */
420 {
421 return 1000;
422 }
423 else if( ( ( partner_capabilities >> 14 ) & 3 ) == 1 ) /* 100Mbps */
424 {
425 return 100;
426 }
427 else /* 10Mbps */
428 {
429 return 10;
430 }
431 #endif /* if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 */
432 }
433 #endif /* Zynq */
434
configure_IEEE_phy_speed(XEmacPs * xemacpsp,unsigned speed)435 unsigned configure_IEEE_phy_speed( XEmacPs * xemacpsp,
436 unsigned speed )
437 {
438 u16 control;
439 u32 phy_addr;
440 int i;
441
442 for( i = 0; i < 2; i++ )
443 {
444 phy_addr = phy_detected[ i ]; /* Both PHYs are connected to ETH0 */
445
446 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2 );
447 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control );
448 control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
449 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control );
450
451 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0 );
452
453 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control );
454 control |= IEEE_ASYMMETRIC_PAUSE_MASK;
455 control |= IEEE_PAUSE_MASK;
456 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control );
457
458 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
459 control &= ~IEEE_CTRL_LINKSPEED_1000M;
460 control &= ~IEEE_CTRL_LINKSPEED_100M;
461 control &= ~IEEE_CTRL_LINKSPEED_10M;
462
463 if( speed == 1000 )
464 {
465 control |= IEEE_CTRL_LINKSPEED_1000M;
466 }
467
468 else if( speed == 100 )
469 {
470 control |= IEEE_CTRL_LINKSPEED_100M;
471 /* Dont advertise PHY speed of 1000 Mbps */
472 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0 );
473 /* Dont advertise PHY speed of 10 Mbps */
474 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
475 ADVERTISE_100 );
476 }
477
478 else if( speed == 10 )
479 {
480 control |= IEEE_CTRL_LINKSPEED_10M;
481 /* Dont advertise PHY speed of 1000 Mbps */
482 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
483 0 );
484 /* Dont advertise PHY speed of 100 Mbps */
485 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
486 ADVERTISE_10 );
487 }
488
489 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
490 control | IEEE_CTRL_RESET_MASK );
491 {
492 volatile int wait;
493
494 for( wait = 0; wait < 100000; wait++ )
495 {
496 }
497 }
498 }
499
500 return 0;
501 }
502
SetUpSLCRDivisors(int mac_baseaddr,int speed)503 static void SetUpSLCRDivisors( int mac_baseaddr,
504 int speed )
505 {
506 volatile u32 slcrBaseAddress;
507
508 #ifndef PEEP
509 u32 SlcrDiv0;
510 u32 SlcrDiv1 = 0;
511 u32 SlcrTxClkCntrl;
512 #endif
513
514 *( volatile unsigned int * ) ( SLCR_UNLOCK_ADDR ) = SLCR_UNLOCK_KEY_VALUE;
515
516 if( ( unsigned long ) mac_baseaddr == EMAC0_BASE_ADDRESS )
517 {
518 slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
519 }
520 else
521 {
522 slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
523 }
524
525 #ifdef PEEP
526 if( speed == 1000 )
527 {
528 *( volatile unsigned int * ) ( slcrBaseAddress ) =
529 SLCR_GEM_1G_CLK_CTRL_VALUE;
530 }
531 else if( speed == 100 )
532 {
533 *( volatile unsigned int * ) ( slcrBaseAddress ) =
534 SLCR_GEM_100M_CLK_CTRL_VALUE;
535 }
536 else
537 {
538 *( volatile unsigned int * ) ( slcrBaseAddress ) =
539 SLCR_GEM_10M_CLK_CTRL_VALUE;
540 }
541 #else /* ifdef PEEP */
542 if( speed == 1000 )
543 {
544 if( ( unsigned long ) mac_baseaddr == EMAC0_BASE_ADDRESS )
545 {
546 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
547 SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
548 SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
549 #endif
550 }
551 else
552 {
553 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
554 SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
555 SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
556 #endif
557 }
558 }
559 else if( speed == 100 )
560 {
561 if( ( unsigned long ) mac_baseaddr == EMAC0_BASE_ADDRESS )
562 {
563 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
564 SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
565 SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
566 #endif
567 }
568 else
569 {
570 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
571 SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
572 SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
573 #endif
574 }
575 }
576 else
577 {
578 if( ( unsigned long ) mac_baseaddr == EMAC0_BASE_ADDRESS )
579 {
580 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
581 SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
582 SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
583 #endif
584 }
585 else
586 {
587 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
588 SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
589 SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
590 #endif
591 }
592 }
593
594 SlcrTxClkCntrl = *( volatile unsigned int * ) ( slcrBaseAddress );
595 SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
596 SlcrTxClkCntrl |= ( SlcrDiv1 << 20 );
597 SlcrTxClkCntrl |= ( SlcrDiv0 << 8 );
598 *( volatile unsigned int * ) ( slcrBaseAddress ) = SlcrTxClkCntrl;
599 #endif /* ifdef PEEP */
600 *( volatile unsigned int * ) ( SLCR_LOCK_ADDR ) = SLCR_LOCK_KEY_VALUE;
601 }
602
603
604 unsigned link_speed;
Phy_Setup(XEmacPs * xemacpsp)605 unsigned Phy_Setup( XEmacPs * xemacpsp )
606 {
607 unsigned long conv_present = 0;
608 unsigned long convspeeddupsetting = 0;
609 unsigned long convphyaddr = 0;
610
611 #ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR
612 convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
613 conv_present = 1;
614 #else
615 #ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR
616 convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
617 conv_present = 1;
618 #endif
619 #endif
620
621 #ifdef ipconfigNIC_LINKSPEED_AUTODETECT
622 link_speed = get_IEEE_phy_speed( xemacpsp );
623
624 if( link_speed == 1000 )
625 {
626 SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 1000 );
627 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
628 }
629 else if( link_speed == 100 )
630 {
631 SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 100 );
632 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
633 }
634 else
635 {
636 SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 10 );
637 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
638 }
639 #elif defined( ipconfigNIC_LINKSPEED1000 )
640 SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 1000 );
641 link_speed = 1000;
642 configure_IEEE_phy_speed( xemacpsp, link_speed );
643 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
644 vTaskDelay( MINIMUM_SLEEP_TIME );
645 #elif defined( ipconfigNIC_LINKSPEED100 )
646 SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 100 );
647 link_speed = 100;
648 configure_IEEE_phy_speed( xemacpsp, link_speed );
649 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
650 vTaskDelay( MINIMUM_SLEEP_TIME );
651 #elif defined( ipconfigNIC_LINKSPEED10 )
652 SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 10 );
653 link_speed = 10;
654 configure_IEEE_phy_speed( xemacpsp, link_speed );
655 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
656 vTaskDelay( MINIMUM_SLEEP_TIME );
657 #endif /* ifdef ipconfigNIC_LINKSPEED_AUTODETECT */
658
659 if( conv_present )
660 {
661 XEmacPs_PhyWrite( xemacpsp, convphyaddr,
662 XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting );
663 }
664
665 FreeRTOS_printf( ( "link speed: %d\n", link_speed ) );
666 return link_speed;
667 }
668