xref: /FreeRTOS-Plus-TCP-v3.1.0/source/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c (revision a4124602cc584fa0658448c229f48a459a84fbb1)
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