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 "NetworkBufferManagement.h"
67
68 #include "Zynq/x_emacpsif.h"
69 #include "xparameters_ps.h"
70 #include "xparameters.h"
71
72
73 int phy_detected = 0;
74
75 /*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
76 *** to run it on a PEEP board
77 ***/
78
79 /* Advertisement control register. */
80 #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
81 #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
82 #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
83 #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
84
85 #define ADVERTISE_100_AND_10 \
86 ( ADVERTISE_10FULL | ADVERTISE_100FULL | \
87 ADVERTISE_10HALF | ADVERTISE_100HALF )
88 #define ADVERTISE_100 ( ADVERTISE_100FULL | ADVERTISE_100HALF )
89 #define ADVERTISE_10 ( ADVERTISE_10FULL | ADVERTISE_10HALF )
90
91 #define ADVERTISE_1000 0x0300
92
93
94 /*#define PHY_REG_00_BMCR 0x00 // Basic mode control register */
95 /*#define PHY_REG_01_BMSR 0x01 // Basic mode status register */
96 /*#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1 */
97 /*#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2 */
98 /*#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg */
99
100 #define IEEE_CONTROL_REG_OFFSET 0
101 #define IEEE_STATUS_REG_OFFSET 1
102 #define IEEE_PHYSID1_OFFSET 2
103 #define IEEE_PHYSID2_OFFSET 3
104 #define IEEE_AUTONEGO_ADVERTISE_REG 4
105 #define IEEE_PARTNER_ABILITIES_1_REG_OFFSET 5
106 #define IEEE_1000_ADVERTISE_REG_OFFSET 9
107 #define IEEE_PARTNER_ABILITIES_3_REG_OFFSET 10
108 #define IEEE_COPPER_SPECIFIC_CONTROL_REG 16
109 #define IEEE_SPECIFIC_STATUS_REG 17
110 #define IEEE_COPPER_SPECIFIC_STATUS_REG_2 19
111 #define IEEE_CONTROL_REG_MAC 21
112 #define IEEE_PAGE_ADDRESS_REGISTER 22
113
114
115 #define IEEE_CTRL_1GBPS_LINKSPEED_MASK 0x2040
116 #define IEEE_CTRL_LINKSPEED_MASK 0x0040
117 #define IEEE_CTRL_LINKSPEED_1000M 0x0040
118 #define IEEE_CTRL_LINKSPEED_100M 0x2000
119 #define IEEE_CTRL_LINKSPEED_10M 0x0000
120 #define IEEE_CTRL_RESET_MASK 0x8000
121 #define IEEE_CTRL_AUTONEGOTIATE_ENABLE 0x1000
122 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
123 #define IEEE_CTRL_RESET 0x9140
124 #define IEEE_CTRL_ISOLATE_DISABLE 0xFBFF
125 #endif
126 #define IEEE_STAT_AUTONEGOTIATE_CAPABLE 0x0008
127 #define IEEE_STAT_AUTONEGOTIATE_COMPLETE 0x0020
128 #define IEEE_STAT_AUTONEGOTIATE_RESTART 0x0200
129 #define IEEE_STAT_1GBPS_EXTENSIONS 0x0100
130 #define IEEE_AN1_ABILITY_MASK 0x1FE0
131 #define IEEE_AN3_ABILITY_MASK_1GBPS 0x0C00
132 #define IEEE_AN1_ABILITY_MASK_100MBPS 0x0380
133 #define IEEE_AN1_ABILITY_MASK_10MBPS 0x0060
134 #define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK 0x0030
135
136 #define IEEE_ASYMMETRIC_PAUSE_MASK 0x0800
137 #define IEEE_PAUSE_MASK 0x0400
138 #define IEEE_AUTONEG_ERROR_MASK 0x8000
139
140 #define XEMACPS_GMII2RGMII_SPEED1000_FD 0x140
141 #define XEMACPS_GMII2RGMII_SPEED100_FD 0x2100
142 #define XEMACPS_GMII2RGMII_SPEED10_FD 0x100
143 #define XEMACPS_GMII2RGMII_REG_NUM 0x10
144
145 /* Frequency setting */
146 #define SLCR_LOCK_ADDR ( XPS_SYS_CTRL_BASEADDR + 0x4 )
147 #define SLCR_UNLOCK_ADDR ( XPS_SYS_CTRL_BASEADDR + 0x8 )
148 #define SLCR_GEM0_CLK_CTRL_ADDR ( XPS_SYS_CTRL_BASEADDR + 0x140 )
149 #define SLCR_GEM1_CLK_CTRL_ADDR ( XPS_SYS_CTRL_BASEADDR + 0x144 )
150 #ifdef PEEP
151 #define SLCR_GEM_10M_CLK_CTRL_VALUE 0x00103031
152 #define SLCR_GEM_100M_CLK_CTRL_VALUE 0x00103001
153 #define SLCR_GEM_1G_CLK_CTRL_VALUE 0x00103011
154 #endif
155 #define SLCR_LOCK_KEY_VALUE 0x767B
156 #define SLCR_UNLOCK_KEY_VALUE 0xDF0D
157 #define SLCR_ADDR_GEM_RST_CTRL ( XPS_SYS_CTRL_BASEADDR + 0x214 )
158 #define EMACPS_SLCR_DIV_MASK 0xFC0FC0FF
159
160 #define EMAC0_BASE_ADDRESS 0xE000B000
161 #define EMAC1_BASE_ADDRESS 0xE000C000
162
163 #define PHY_ADDRESS_COUNT 32
164
165 #define MINIMUM_SLEEP_TIME 2
166
167
detect_phy(XEmacPs * xemacpsp)168 static int detect_phy( XEmacPs * xemacpsp )
169 {
170 u16 id_lower, id_upper;
171 u32 phy_addr, id;
172
173 for( phy_addr = 0; phy_addr < PHY_ADDRESS_COUNT; phy_addr++ )
174 {
175 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_PHYSID1_OFFSET, &id_lower );
176
177 if( ( id_lower != ( u16 ) 0xFFFFu ) && ( id_lower != ( u16 ) 0x0u ) )
178 {
179 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_PHYSID2_OFFSET, &id_upper );
180 id = ( ( ( uint32_t ) id_upper ) << 16 ) | ( id_lower & 0xFFF0 );
181 FreeRTOS_printf( ( "XEmacPs detect_phy: %04lX at address %d.\n", id, phy_addr ) );
182 phy_detected = phy_addr;
183 return phy_addr;
184 }
185 }
186
187 FreeRTOS_printf( ( "XEmacPs detect_phy: No PHY detected. Assuming a PHY at address 0\n" ) );
188
189 /* default to zero */
190 return 0;
191 }
192
193 #ifdef PEEP
get_IEEE_phy_speed(XEmacPs * xemacpsp)194 unsigned get_IEEE_phy_speed( XEmacPs * xemacpsp )
195 {
196 u16 control;
197 u16 status;
198 u16 partner_capabilities;
199 u16 partner_capabilities_1000;
200 u16 phylinkspeed;
201 u32 phy_addr = detect_phy( xemacpsp );
202
203 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
204 ADVERTISE_1000 );
205 /* Advertise PHY speed of 100 and 10 Mbps */
206 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
207 ADVERTISE_100_AND_10 );
208
209 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
210 &control );
211 control |= ( IEEE_CTRL_AUTONEGOTIATE_ENABLE |
212 IEEE_STAT_AUTONEGOTIATE_RESTART );
213
214 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );
215
216 /* Read PHY control and status registers is successful. */
217 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
218 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status );
219
220 if( ( control & IEEE_CTRL_AUTONEGOTIATE_ENABLE ) && ( status &
221 IEEE_STAT_AUTONEGOTIATE_CAPABLE ) )
222 {
223 while( !( status & IEEE_STAT_AUTONEGOTIATE_COMPLETE ) )
224 {
225 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
226 &status );
227 }
228
229 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,
230 &partner_capabilities );
231
232 if( status & IEEE_STAT_1GBPS_EXTENSIONS )
233 {
234 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,
235 &partner_capabilities_1000 );
236
237 if( partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS )
238 {
239 return 1000;
240 }
241 }
242
243 if( partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS )
244 {
245 return 100;
246 }
247
248 if( partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS )
249 {
250 return 10;
251 }
252
253 FreeRTOS_printf( ( "%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\n",
254 __FUNCTION__ ) );
255 return 10;
256 }
257 else
258 {
259 /* Update TEMAC speed accordingly */
260 if( status & IEEE_STAT_1GBPS_EXTENSIONS )
261 {
262 /* Get commanded link speed */
263 phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;
264
265 switch( phylinkspeed )
266 {
267 case ( IEEE_CTRL_LINKSPEED_1000M ):
268 return 1000;
269
270 case ( IEEE_CTRL_LINKSPEED_100M ):
271 return 100;
272
273 case ( IEEE_CTRL_LINKSPEED_10M ):
274 return 10;
275
276 default:
277 FreeRTOS_printf( ( "%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\n",
278 __FUNCTION__, phylinkspeed ) );
279 return 10;
280 }
281 }
282 else
283 {
284 return ( control & IEEE_CTRL_LINKSPEED_MASK ) ? 100 : 10;
285 }
286 }
287 }
288
289 #else /* Zynq */
get_IEEE_phy_speed(XEmacPs * xemacpsp)290 unsigned get_IEEE_phy_speed( XEmacPs * xemacpsp )
291 {
292 u16 temp;
293 u16 control;
294 u16 status;
295 u16 partner_capabilities;
296
297 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
298 u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;
299 #else
300 u32 phy_addr = detect_phy( xemacpsp );
301 #endif
302 FreeRTOS_printf( ( "Start PHY autonegotiation \n" ) );
303
304 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
305 #else
306 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2 );
307 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control );
308 control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
309 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control );
310
311 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0 );
312
313 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control );
314 control |= IEEE_ASYMMETRIC_PAUSE_MASK;
315 control |= IEEE_PAUSE_MASK;
316 control |= ADVERTISE_100;
317 control |= ADVERTISE_10;
318 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control );
319
320 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
321 &control );
322 control |= ADVERTISE_1000;
323 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
324 control );
325
326 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0 );
327 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
328 &control );
329 control |= ( 7 << 12 ); /* max number of gigabit attempts */
330 control |= ( 1 << 11 ); /* enable downshift */
331 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
332 control );
333 #endif /* if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 */
334 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
335 control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
336 control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
337 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
338 control &= IEEE_CTRL_ISOLATE_DISABLE;
339 #endif
340
341 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );
342
343
344 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
345 #else
346 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
347 control |= IEEE_CTRL_RESET_MASK;
348 XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );
349
350 while( 1 )
351 {
352 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
353
354 if( control & IEEE_CTRL_RESET_MASK )
355 {
356 continue;
357 }
358 else
359 {
360 break;
361 }
362 }
363 #endif /* if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 */
364 FreeRTOS_printf( ( "Waiting for PHY to complete autonegotiation.\n" ) );
365
366 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status );
367
368 while( !( status & IEEE_STAT_AUTONEGOTIATE_COMPLETE ) )
369 {
370 vTaskDelay( MINIMUM_SLEEP_TIME );
371 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
372 #else
373 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,
374 &temp );
375
376 if( temp & IEEE_AUTONEG_ERROR_MASK )
377 {
378 FreeRTOS_printf( ( "Auto negotiation error \n" ) );
379 }
380 #endif
381 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
382 &status );
383 }
384
385 FreeRTOS_printf( ( "autonegotiation complete \n" ) );
386
387 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
388 #else
389 XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities );
390 #endif
391
392 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
393 FreeRTOS_printf( ( "Waiting for Link to be up; Polling for SGMII core Reg \n" ) );
394 XEmacPs_PhyRead( xemacpsp, phy_addr, 5, &temp );
395
396 while( !( temp & 0x8000 ) )
397 {
398 XEmacPs_PhyRead( xemacpsp, phy_addr, 5, &temp );
399 }
400
401 if( ( temp & 0x0C00 ) == 0x0800 )
402 {
403 XEmacPs_PhyRead( xemacpsp, phy_addr, 0, &temp );
404 return 1000;
405 }
406 else if( ( temp & 0x0C00 ) == 0x0400 )
407 {
408 XEmacPs_PhyRead( xemacpsp, phy_addr, 0, &temp );
409 return 100;
410 }
411 else if( ( temp & 0x0C00 ) == 0x0000 )
412 {
413 XEmacPs_PhyRead( xemacpsp, phy_addr, 0, &temp );
414 return 10;
415 }
416 else
417 {
418 FreeRTOS_printf( ( "get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\n" ) );
419 XEmacPs_PhyRead( xemacpsp, phy_addr, 0, &temp );
420 XEmacPs_PhyWrite( xemacpsp, phy_addr, 0, 0x0100 );
421 return 10;
422 }
423 #else /* if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 */
424 if( ( ( partner_capabilities >> 14 ) & 3 ) == 2 ) /* 1000Mbps */
425 {
426 return 1000;
427 }
428 else if( ( ( partner_capabilities >> 14 ) & 3 ) == 1 ) /* 100Mbps */
429 {
430 return 100;
431 }
432 else /* 10Mbps */
433 {
434 return 10;
435 }
436 #endif /* if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1 */
437 }
438 #endif /* ifdef PEEP */
439
configure_IEEE_phy_speed(XEmacPs * xemacpsp,unsigned speed)440 unsigned configure_IEEE_phy_speed( XEmacPs * xemacpsp,
441 unsigned speed )
442 {
443 u16 control;
444 u32 phy_addr = detect_phy( xemacpsp );
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 return 0;
499 }
500
SetUpSLCRDivisors(int mac_baseaddr,int speed)501 static void SetUpSLCRDivisors( int mac_baseaddr,
502 int speed )
503 {
504 volatile u32 slcrBaseAddress;
505
506 #ifndef PEEP
507 u32 SlcrDiv0;
508 u32 SlcrDiv1 = 0;
509 u32 SlcrTxClkCntrl;
510 #endif
511
512 *( volatile unsigned int * ) ( SLCR_UNLOCK_ADDR ) = SLCR_UNLOCK_KEY_VALUE;
513
514 if( ( unsigned long ) mac_baseaddr == EMAC0_BASE_ADDRESS )
515 {
516 slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
517 }
518 else
519 {
520 slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
521 }
522
523 #ifdef PEEP
524 if( speed == 1000 )
525 {
526 *( volatile unsigned int * ) ( slcrBaseAddress ) =
527 SLCR_GEM_1G_CLK_CTRL_VALUE;
528 }
529 else if( speed == 100 )
530 {
531 *( volatile unsigned int * ) ( slcrBaseAddress ) =
532 SLCR_GEM_100M_CLK_CTRL_VALUE;
533 }
534 else
535 {
536 *( volatile unsigned int * ) ( slcrBaseAddress ) =
537 SLCR_GEM_10M_CLK_CTRL_VALUE;
538 }
539 #else /* ifdef PEEP */
540 if( speed == 1000 )
541 {
542 if( ( unsigned long ) mac_baseaddr == EMAC0_BASE_ADDRESS )
543 {
544 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
545 SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
546 SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
547 #endif
548 }
549 else
550 {
551 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
552 SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
553 SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
554 #endif
555 }
556 }
557 else if( speed == 100 )
558 {
559 if( ( unsigned long ) mac_baseaddr == EMAC0_BASE_ADDRESS )
560 {
561 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
562 SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
563 SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
564 #endif
565 }
566 else
567 {
568 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
569 SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
570 SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
571 #endif
572 }
573 }
574 else
575 {
576 if( ( unsigned long ) mac_baseaddr == EMAC0_BASE_ADDRESS )
577 {
578 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
579 SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
580 SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
581 #endif
582 }
583 else
584 {
585 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
586 SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
587 SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
588 #endif
589 }
590 }
591
592 SlcrTxClkCntrl = *( volatile unsigned int * ) ( slcrBaseAddress );
593 SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
594 SlcrTxClkCntrl |= ( SlcrDiv1 << 20 );
595 SlcrTxClkCntrl |= ( SlcrDiv0 << 8 );
596 *( volatile unsigned int * ) ( slcrBaseAddress ) = SlcrTxClkCntrl;
597 #endif /* ifdef PEEP */
598 *( volatile unsigned int * ) ( SLCR_LOCK_ADDR ) = SLCR_LOCK_KEY_VALUE;
599 }
600
601
602 unsigned link_speed;
Phy_Setup(XEmacPs * xemacpsp)603 unsigned Phy_Setup( XEmacPs * xemacpsp )
604 {
605 unsigned long conv_present = 0;
606 unsigned long convspeeddupsetting = 0;
607 unsigned long convphyaddr = 0;
608
609 #ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR
610 convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
611 conv_present = 1;
612 #else
613 #ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR
614 convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
615 conv_present = 1;
616 #endif
617 #endif
618
619 #ifdef ipconfigNIC_LINKSPEED_AUTODETECT
620 link_speed = get_IEEE_phy_speed( xemacpsp );
621
622 if( link_speed == 1000 )
623 {
624 SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 1000 );
625 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
626 }
627 else if( link_speed == 100 )
628 {
629 SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 100 );
630 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
631 }
632 else
633 {
634 SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 10 );
635 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
636 }
637 #elif defined( ipconfigNIC_LINKSPEED1000 )
638 SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 1000 );
639 link_speed = 1000;
640 configure_IEEE_phy_speed( xemacpsp, link_speed );
641 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
642 vTaskDelay( MINIMUM_SLEEP_TIME );
643 #elif defined( ipconfigNIC_LINKSPEED100 )
644 SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 100 );
645 link_speed = 100;
646 configure_IEEE_phy_speed( xemacpsp, link_speed );
647 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
648 vTaskDelay( MINIMUM_SLEEP_TIME );
649 #elif defined( ipconfigNIC_LINKSPEED10 )
650 SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 10 );
651 link_speed = 10;
652 configure_IEEE_phy_speed( xemacpsp, link_speed );
653 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
654 vTaskDelay( MINIMUM_SLEEP_TIME );
655 #endif /* ifdef ipconfigNIC_LINKSPEED_AUTODETECT */
656
657 if( conv_present )
658 {
659 XEmacPs_PhyWrite( xemacpsp, convphyaddr,
660 XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting );
661 }
662
663 FreeRTOS_printf( ( "link speed: %d\n", link_speed ) );
664 return link_speed;
665 }
666