xref: /FreeRTOS-Plus-TCP-v4.0.0/source/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c (revision 2d3f4daa567ffe71aeda2e0f6d0bc02850db0627)
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