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 #include "x_emacpsif.h"
57 /*#include "lwipopts.h" */
58 #include "xparameters_ps.h"
59 #include "xparameters.h"
60 
61 /* FreeRTOS includes. */
62 #include "FreeRTOS.h"
63 #include "task.h"
64 #include "queue.h"
65 #include "semphr.h"
66 
67 /*/ * FreeRTOS+TCP includes. * / */
68 /* FreeRTOS+TCP includes. */
69 #include "FreeRTOS_IP.h"
70 #include "FreeRTOS_Sockets.h"
71 #include "FreeRTOS_IP_Private.h"
72 #include "NetworkBufferManagement.h"
73 
74 #define NOP()    asm ( "nop" );
75 
76 #define phyMIN_PHY_ADDRESS    0
77 #define phyMAX_PHY_ADDRESS    31
78 
test_sleep(uint32_t uxTicks)79 void test_sleep( uint32_t uxTicks )
80 {
81     for( uint32_t j = 0U; j < uxTicks; j++ )
82     {
83         for( uint32_t i = 0U; i < 100000000U; i++ )
84         {
85             NOP();
86         }
87     }
88 }
89 
my_sleep(uint32_t uxTicks)90 void my_sleep( uint32_t uxTicks )
91 {
92     sleep( uxTicks );
93 }
94 
95 /*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
96  *** to run it on a PEEP board
97  ***/
98 
99 /* Advertisement control register. */
100 #define ADVERTISE_10HALF      0x0020    /* Try for 10mbps half-duplex  */
101 #define ADVERTISE_10FULL      0x0040    /* Try for 10mbps full-duplex  */
102 #define ADVERTISE_100HALF     0x0080    /* Try for 100mbps half-duplex */
103 #define ADVERTISE_100FULL     0x0100    /* Try for 100mbps full-duplex */
104 
105 #define ADVERTISE_1000FULL    0x0200
106 #define ADVERTISE_1000HALF    0x0100
107 
108 #define ADVERTISE_100_AND_10                 \
109     ( ADVERTISE_10FULL | ADVERTISE_100FULL | \
110       ADVERTISE_10HALF | ADVERTISE_100HALF )
111 #define ADVERTISE_100         ( ADVERTISE_100FULL | ADVERTISE_100HALF )
112 #define ADVERTISE_10          ( ADVERTISE_10FULL | ADVERTISE_10HALF )
113 
114 #define ADVERTISE_1000        0x0300
115 
116 /*#define PHY_REG_00_BMCR            0x00 // Basic mode control register */
117 /*#define PHY_REG_01_BMSR            0x01 // Basic mode status register */
118 /*#define PHY_REG_02_PHYSID1         0x02 // PHYS ID 1 */
119 /*#define PHY_REG_03_PHYSID2         0x03 // PHYS ID 2 */
120 /*#define PHY_REG_04_ADVERTISE       0x04 // Advertisement control reg */
121 
122 #define IEEE_CONTROL_REG_OFFSET                0
123 #define IEEE_STATUS_REG_OFFSET                 1
124 #define IEEE_AUTONEGO_ADVERTISE_REG            4
125 #define IEEE_PARTNER_ABILITIES_1_REG_OFFSET    5
126 #define IEEE_PARTNER_ABILITIES_2_REG_OFFSET    8
127 #define IEEE_PARTNER_ABILITIES_3_REG_OFFSET    10
128 #define IEEE_1000_ADVERTISE_REG_OFFSET         9
129 #define IEEE_MMD_ACCESS_CONTROL_REG            13
130 #define IEEE_MMD_ACCESS_ADDRESS_DATA_REG       14
131 #define IEEE_COPPER_SPECIFIC_CONTROL_REG       16
132 #define IEEE_SPECIFIC_STATUS_REG               17
133 #define IEEE_COPPER_SPECIFIC_STATUS_REG_2      19
134 #define IEEE_EXT_PHY_SPECIFIC_CONTROL_REG      20
135 #define IEEE_CONTROL_REG_MAC                   21
136 #define IEEE_PAGE_ADDRESS_REGISTER             22
137 
138 #define IEEE_CTRL_1GBPS_LINKSPEED_MASK         0x2040
139 #define IEEE_CTRL_LINKSPEED_MASK               0x0040
140 #define IEEE_CTRL_LINKSPEED_1000M              0x0040
141 #define IEEE_CTRL_LINKSPEED_100M               0x2000
142 #define IEEE_CTRL_LINKSPEED_10M                0x0000
143 #define IEEE_CTRL_FULL_DUPLEX                  0x100
144 #define IEEE_CTRL_RESET_MASK                   0x8000
145 #define IEEE_CTRL_AUTONEGOTIATE_ENABLE         0x1000
146 #define IEEE_STAT_AUTONEGOTIATE_CAPABLE        0x0008
147 #define IEEE_STAT_AUTONEGOTIATE_COMPLETE       0x0020
148 #define IEEE_STAT_AUTONEGOTIATE_RESTART        0x0200
149 #define IEEE_STAT_LINK_STATUS                  0x0004
150 #define IEEE_STAT_1GBPS_EXTENSIONS             0x0100
151 #define IEEE_AN1_ABILITY_MASK                  0x1FE0
152 #define IEEE_AN3_ABILITY_MASK_1GBPS            0x0C00
153 #define IEEE_AN1_ABILITY_MASK_100MBPS          0x0380
154 #define IEEE_AN1_ABILITY_MASK_10MBPS           0x0060
155 #define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK     0x0030
156 
157 #define IEEE_SPEED_MASK                        0xC000
158 #define IEEE_SPEED_1000                        0x8000
159 #define IEEE_SPEED_100                         0x4000
160 
161 #define IEEE_ASYMMETRIC_PAUSE_MASK             0x0800
162 #define IEEE_PAUSE_MASK                        0x0400
163 #define IEEE_AUTONEG_ERROR_MASK                0x8000
164 
165 #define IEEE_MMD_ACCESS_CTRL_DEVAD_MASK        0x1F
166 #define IEEE_MMD_ACCESS_CTRL_PIDEVAD_MASK      0x801F
167 #define IEEE_MMD_ACCESS_CTRL_NOPIDEVAD_MASK    0x401F
168 
169 #define PHY_DETECT_REG                         1
170 #define PHY_IDENTIFIER_1_REG                   2
171 #define PHY_IDENTIFIER_2_REG                   3
172 #define PHY_DETECT_MASK                        0x1808
173 #define PHY_MARVELL_IDENTIFIER                 0x0141
174 #define PHY_TI_IDENTIFIER                      0x2000
175 #define PHY_REALTEK_IDENTIFIER                 0x001c
176 #define PHY_AR8035_IDENTIFIER                  0x004D
177 #define PHY_XILINX_PCS_PMA_ID1                 0x0174
178 #define PHY_XILINX_PCS_PMA_ID2                 0x0C00
179 
180 #define XEMACPS_GMII2RGMII_SPEED1000_FD        0x140
181 #define XEMACPS_GMII2RGMII_SPEED100_FD         0x2100
182 #define XEMACPS_GMII2RGMII_SPEED10_FD          0x100
183 #define XEMACPS_GMII2RGMII_REG_NUM             0x10
184 
185 #define PHY_REGCR                              0x0D
186 #define PHY_ADDAR                              0x0E
187 #define PHY_RGMIIDCTL                          0x86
188 #define PHY_RGMIICTL                           0x32
189 #define PHY_STS                                0x11
190 #define PHY_TI_CR                              0x10
191 #define PHY_TI_CFG4                            0x31
192 
193 #define PHY_REGCR_ADDR                         0x001F
194 #define PHY_REGCR_DATA                         0x401F
195 #define PHY_TI_CRVAL                           0x5048
196 #define PHY_TI_CFG4RESVDBIT7                   0x80
197 
198 /* Frequency setting */
199 #define SLCR_LOCK_ADDR                         ( XPS_SYS_CTRL_BASEADDR + 0x4 )
200 #define SLCR_UNLOCK_ADDR                       ( XPS_SYS_CTRL_BASEADDR + 0x8 )
201 #define SLCR_GEM0_CLK_CTRL_ADDR                ( XPS_SYS_CTRL_BASEADDR + 0x140 )
202 #define SLCR_GEM1_CLK_CTRL_ADDR                ( XPS_SYS_CTRL_BASEADDR + 0x144 )
203 #ifdef PEEP
204     #define SLCR_GEM_10M_CLK_CTRL_VALUE        0x00103031
205     #define SLCR_GEM_100M_CLK_CTRL_VALUE       0x00103001
206     #define SLCR_GEM_1G_CLK_CTRL_VALUE         0x00103011
207 #endif
208 #define SLCR_GEM_SRCSEL_EMIO                   0x40
209 #define SLCR_LOCK_KEY_VALUE                    0x767B
210 #define SLCR_UNLOCK_KEY_VALUE                  0xDF0D
211 #define SLCR_ADDR_GEM_RST_CTRL                 ( XPS_SYS_CTRL_BASEADDR + 0x214 )
212 #define EMACPS_SLCR_DIV_MASK                   0xFC0FC0FF
213 
214 #define ZYNQ_EMACPS_0_BASEADDR                 0xE000B000
215 #define ZYNQ_EMACPS_1_BASEADDR                 0xE000C000
216 
217 #define ZYNQMP_EMACPS_0_BASEADDR               0xFF0B0000
218 #define ZYNQMP_EMACPS_1_BASEADDR               0xFF0C0000
219 #define ZYNQMP_EMACPS_2_BASEADDR               0xFF0D0000
220 #define ZYNQMP_EMACPS_3_BASEADDR               0xFF0E0000
221 
222 #define CRL_APB_GEM0_REF_CTRL                  0xFF5E0050
223 #define CRL_APB_GEM1_REF_CTRL                  0xFF5E0054
224 #define CRL_APB_GEM2_REF_CTRL                  0xFF5E0058
225 #define CRL_APB_GEM3_REF_CTRL                  0xFF5E005C
226 
227 #define CRL_APB_GEM_DIV0_MASK                  0x00003F00
228 #define CRL_APB_GEM_DIV0_SHIFT                 8
229 #define CRL_APB_GEM_DIV1_MASK                  0x003F0000
230 #define CRL_APB_GEM_DIV1_SHIFT                 16
231 
232 #define VERSAL_EMACPS_0_BASEADDR               0xFF0C0000
233 #define VERSAL_EMACPS_1_BASEADDR               0xFF0D0000
234 
235 #define VERSAL_CRL_GEM0_REF_CTRL               0xFF5E0118
236 #define VERSAL_CRL_GEM1_REF_CTRL               0xFF5E011C
237 
238 #define VERSAL_CRL_GEM_DIV_MASK                0x0003FF00
239 #define VERSAL_CRL_APB_GEM_DIV_SHIFT           8
240 
241 
242 #define GEM_VERSION_ZYNQMP                     7
243 #define GEM_VERSION_VERSAL                     0x107
244 
245 u32 phymapemac0[ 32 ];
246 u32 phymapemac1[ 32 ];
247 
248 static uint16_t prvAR803x_debug_reg_read( XEmacPs * xemacpsp,
249                                           uint32_t phy_addr,
250                                           u16 reg );
251 static uint16_t prvAR803x_debug_reg_write( XEmacPs * xemacpsp,
252                                            uint32_t phy_addr,
253                                            u16 reg,
254                                            u16 value );
255 static int prvAR803x_debug_reg_mask( XEmacPs * xemacpsp,
256                                      uint32_t phy_addr,
257                                      u16 reg,
258                                      u16 clear,
259                                      u16 set );
260 static void prvSET_AR803x_TX_Timing( XEmacPs * xemacpsp,
261                                      uint32_t phy_addr );
262 
ulDetecPHY(XEmacPs * xemacpsp)263 uint32_t ulDetecPHY( XEmacPs * xemacpsp )
264 {
265     u16 PhyReg1;
266     u16 PhyReg2;
267     u32 phy_addr;
268     u32 Status;
269 
270     for( phy_addr = phyMIN_PHY_ADDRESS; phy_addr <= phyMAX_PHY_ADDRESS; phy_addr++ )
271     {
272         Status = XEmacPs_PhyRead( xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG, &PhyReg1 );
273         Status |= XEmacPs_PhyRead( xemacpsp, phy_addr, PHY_IDENTIFIER_2_REG, &PhyReg2 );
274 
275         if( ( Status == XST_SUCCESS ) &&
276             ( PhyReg1 > 0x0000 ) && ( PhyReg1 < 0xffff ) &&
277             ( PhyReg2 > 0x0000 ) && ( PhyReg2 < 0xffff ) )
278         {
279             /* Found a valid PHY address */
280             break;
281         }
282     }
283 
284     return ( phy_addr <= phyMAX_PHY_ADDRESS ) ? phy_addr : ~0U;
285 }
286 
287 
288 
configure_IEEE_phy_speed_US(XEmacPs * xemacpsp,unsigned speed,u32 phy_addr)289 unsigned configure_IEEE_phy_speed_US( XEmacPs * xemacpsp,
290                                       unsigned speed,
291                                       u32 phy_addr )
292 {
293     u16 control;
294 
295     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2 );
296     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control );
297     control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
298     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control );
299 
300     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0 );
301 
302     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control );
303     control |= IEEE_ASYMMETRIC_PAUSE_MASK;
304     control |= IEEE_PAUSE_MASK;
305     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control );
306 
307     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
308     control &= ~IEEE_CTRL_LINKSPEED_1000M;
309     control &= ~IEEE_CTRL_LINKSPEED_100M;
310     control &= ~IEEE_CTRL_LINKSPEED_10M;
311 
312     if( speed == 1000 )
313     {
314         control |= IEEE_CTRL_LINKSPEED_1000M;
315     }
316 
317     else if( speed == 100 )
318     {
319         control |= IEEE_CTRL_LINKSPEED_100M;
320         /* Dont advertise PHY speed of 1000 Mbps */
321         XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0 );
322         /* Dont advertise PHY speed of 10 Mbps */
323         XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
324                           ADVERTISE_100 );
325     }
326 
327     else if( speed == 10 )
328     {
329         control |= IEEE_CTRL_LINKSPEED_10M;
330         /* Dont advertise PHY speed of 1000 Mbps */
331         XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0 );
332         /* Dont advertise PHY speed of 100 Mbps */
333         XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
334                           ADVERTISE_10 );
335     }
336 
337     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
338                       control | IEEE_CTRL_RESET_MASK );
339     {
340         volatile int wait;
341 
342         for( wait = 0; wait < 100000; wait++ )
343         {
344         }
345     }
346     return 0;
347 }
348 
get_TI_phy_speed(XEmacPs * xemacpsp,uint32_t phy_addr)349 static uint32_t get_TI_phy_speed( XEmacPs * xemacpsp,
350                                   uint32_t phy_addr )
351 {
352     uint16_t control;
353     uint16_t status;
354     uint16_t status_speed;
355     uint32_t timeout_counter = 0;
356     uint32_t phyregtemp;
357     int i;
358     uint32_t RetStatus;
359 
360     XEmacPs_PhyRead( xemacpsp, phy_addr, 0x1F, ( uint16_t * ) &phyregtemp );
361     phyregtemp |= 0x4000;
362     XEmacPs_PhyWrite( xemacpsp, phy_addr, 0x1F, phyregtemp );
363     RetStatus = XEmacPs_PhyRead( xemacpsp, phy_addr, 0x1F, ( uint16_t * ) &phyregtemp );
364 
365     if( RetStatus != XST_SUCCESS )
366     {
367         FreeRTOS_printf( ( "Error during sw reset \n\r" ) );
368         return XST_FAILURE;
369     }
370 
371     XEmacPs_PhyRead( xemacpsp, phy_addr, 0, ( uint16_t * ) &phyregtemp );
372     phyregtemp |= 0x8000;
373     XEmacPs_PhyWrite( xemacpsp, phy_addr, 0, phyregtemp );
374 
375     /*
376      * Delay
377      */
378     for( i = 0; i < 1000000000; i++ )
379     {
380     }
381 
382     RetStatus = XEmacPs_PhyRead( xemacpsp, phy_addr, 0, ( uint16_t * ) &phyregtemp );
383 
384     if( RetStatus != XST_SUCCESS )
385     {
386         FreeRTOS_printf( ( "Error during reset \n\r" ) );
387         return XST_FAILURE;
388     }
389 
390     /* FIFO depth */
391     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_TI_CR, PHY_TI_CRVAL );
392     RetStatus = XEmacPs_PhyRead( xemacpsp, phy_addr, PHY_TI_CR, ( uint16_t * ) &phyregtemp );
393 
394     if( RetStatus != XST_SUCCESS )
395     {
396         FreeRTOS_printf( ( "Error writing to 0x10 \n\r" ) );
397         return XST_FAILURE;
398     }
399 
400     /* TX/RX tuning */
401     /* Write to PHY_RGMIIDCTL */
402     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR );
403     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL );
404     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA );
405     RetStatus = XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_ADDAR, 0xA8 );
406 
407     if( RetStatus != XST_SUCCESS )
408     {
409         FreeRTOS_printf( ( "Error in tuning" ) );
410         return XST_FAILURE;
411     }
412 
413     /* Read PHY_RGMIIDCTL */
414     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR );
415     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIIDCTL );
416     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA );
417     RetStatus = XEmacPs_PhyRead( xemacpsp, phy_addr, PHY_ADDAR, ( uint16_t * ) &phyregtemp );
418 
419     if( RetStatus != XST_SUCCESS )
420     {
421         FreeRTOS_printf( ( "Error in tuning" ) );
422         return XST_FAILURE;
423     }
424 
425     /* Write PHY_RGMIICTL */
426     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR );
427     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL );
428     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA );
429     RetStatus = XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_ADDAR, 0xD3 );
430 
431     if( RetStatus != XST_SUCCESS )
432     {
433         FreeRTOS_printf( ( "Error in tuning" ) );
434         return XST_FAILURE;
435     }
436 
437     /* Read PHY_RGMIICTL */
438     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR );
439     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_ADDAR, PHY_RGMIICTL );
440     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA );
441     RetStatus = XEmacPs_PhyRead( xemacpsp, phy_addr, PHY_ADDAR, ( uint16_t * ) &phyregtemp );
442 
443     if( RetStatus != XST_SUCCESS )
444     {
445         FreeRTOS_printf( ( "Error in tuning" ) );
446         return XST_FAILURE;
447     }
448 
449     /* SW workaround for unstable link when RX_CTRL is not STRAP MODE 3 or 4 */
450     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR );
451     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4 );
452     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA );
453     RetStatus = XEmacPs_PhyRead( xemacpsp, phy_addr, PHY_ADDAR, ( uint16_t * ) &phyregtemp );
454     phyregtemp &= ~( PHY_TI_CFG4RESVDBIT7 );
455     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_ADDR );
456     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_ADDAR, PHY_TI_CFG4 );
457     XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_REGCR, PHY_REGCR_DATA );
458     RetStatus = XEmacPs_PhyWrite( xemacpsp, phy_addr, PHY_ADDAR, phyregtemp );
459 
460     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control );
461     control |= IEEE_ASYMMETRIC_PAUSE_MASK;
462     control |= IEEE_PAUSE_MASK;
463     control |= ADVERTISE_100;
464     control |= ADVERTISE_10;
465     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control );
466 
467     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
468                      &control );
469     control |= ADVERTISE_1000;
470     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
471                       control );
472 
473     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
474     control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
475     control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
476     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );
477 
478     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
479     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status );
480 
481     FreeRTOS_printf( ( "Waiting for PHY to complete autonegotiation.\n" ) );
482 
483     while( !( status & IEEE_STAT_AUTONEGOTIATE_COMPLETE ) )
484     {
485         my_sleep( 1 );
486         timeout_counter++;
487 
488         if( timeout_counter == 30 )
489         {
490             FreeRTOS_printf( ( "Auto negotiation error \n" ) );
491             return XST_FAILURE;
492         }
493 
494         XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status );
495     }
496 
497     FreeRTOS_printf( ( "autonegotiation complete \n" ) );
498 
499     XEmacPs_PhyRead( xemacpsp, phy_addr, PHY_STS, &status_speed );
500 
501     if( ( status_speed & 0xC000 ) == 0x8000 )
502     {
503         return 1000;
504     }
505     else if( ( status_speed & 0xC000 ) == 0x4000 )
506     {
507         return 100;
508     }
509     else
510     {
511         return 10;
512     }
513 
514     return XST_SUCCESS;
515 }
516 
get_Marvell_phy_speed(XEmacPs * xemacpsp,uint32_t phy_addr)517 static uint32_t get_Marvell_phy_speed( XEmacPs * xemacpsp,
518                                        uint32_t phy_addr )
519 {
520     uint16_t temp;
521     uint16_t control;
522     uint16_t status;
523     uint16_t status_speed;
524     uint32_t timeout_counter = 0;
525     uint32_t temp_speed;
526 
527     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2 );
528     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control );
529     control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
530     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control );
531 
532     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0 );
533 
534     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control );
535     control |= IEEE_ASYMMETRIC_PAUSE_MASK;
536     control |= IEEE_PAUSE_MASK;
537     control |= ADVERTISE_100;
538     control |= ADVERTISE_10;
539     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control );
540 
541     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
542                      &control );
543     control |= ADVERTISE_1000;
544     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
545                       control );
546 
547     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0 );
548     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
549                      &control );
550     control |= ( 7 << 12 ); /* max number of gigabit attempts */
551     control |= ( 1 << 11 ); /* enable downshift */
552     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
553                       control );
554     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
555     control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
556     control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
557     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );
558 
559     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
560     control |= IEEE_CTRL_RESET_MASK;
561     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );
562 
563     while( 1 )
564     {
565         XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
566 
567         if( control & IEEE_CTRL_RESET_MASK )
568         {
569             continue;
570         }
571         else
572         {
573             break;
574         }
575     }
576 
577     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status );
578 
579     FreeRTOS_printf( ( "Waiting for PHY to complete autonegotiation.\n" ) );
580 
581     while( !( status & IEEE_STAT_AUTONEGOTIATE_COMPLETE ) )
582     {
583         my_sleep( 1 );
584         XEmacPs_PhyRead( xemacpsp, phy_addr,
585                          IEEE_COPPER_SPECIFIC_STATUS_REG_2, &temp );
586         timeout_counter++;
587 
588         if( timeout_counter == 30 )
589         {
590             FreeRTOS_printf( ( "Auto negotiation error \n" ) );
591             return XST_FAILURE;
592         }
593 
594         XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status );
595     }
596 
597     FreeRTOS_printf( ( "autonegotiation complete \n" ) );
598 
599     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG,
600                      &status_speed );
601 
602     if( status_speed & 0x400 )
603     {
604         temp_speed = status_speed & IEEE_SPEED_MASK;
605 
606         if( temp_speed == IEEE_SPEED_1000 )
607         {
608             return 1000;
609         }
610         else if( temp_speed == IEEE_SPEED_100 )
611         {
612             return 100;
613         }
614         else
615         {
616             return 10;
617         }
618     }
619 
620     return XST_SUCCESS;
621 }
622 
get_Realtek_phy_speed(XEmacPs * xemacpsp,uint32_t phy_addr)623 static uint32_t get_Realtek_phy_speed( XEmacPs * xemacpsp,
624                                        uint32_t phy_addr )
625 {
626     uint16_t control;
627     uint16_t status;
628     uint16_t status_speed;
629     uint32_t timeout_counter = 0;
630     uint32_t temp_speed;
631 
632     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control );
633     control |= IEEE_ASYMMETRIC_PAUSE_MASK;
634     control |= IEEE_PAUSE_MASK;
635     control |= ADVERTISE_100;
636     control |= ADVERTISE_10;
637     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control );
638 
639     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
640                      &control );
641     control |= ADVERTISE_1000;
642     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
643                       control );
644 
645     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
646     control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
647     control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
648     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );
649 
650     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
651     control |= IEEE_CTRL_RESET_MASK;
652     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control );
653 
654     while( 1 )
655     {
656         XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control );
657 
658         if( control & IEEE_CTRL_RESET_MASK )
659         {
660             continue;
661         }
662         else
663         {
664             break;
665         }
666     }
667 
668     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status );
669 
670     FreeRTOS_printf( ( "Waiting for PHY to complete autonegotiation.\n" ) );
671 
672     while( !( status & IEEE_STAT_AUTONEGOTIATE_COMPLETE ) )
673     {
674         my_sleep( 1 );
675         timeout_counter++;
676 
677         if( timeout_counter == 30 )
678         {
679             FreeRTOS_printf( ( "Auto negotiation error \n" ) );
680             return XST_FAILURE;
681         }
682 
683         XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status );
684     }
685 
686     FreeRTOS_printf( ( "autonegotiation complete \n" ) );
687 
688     XEmacPs_PhyRead( xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG,
689                      &status_speed );
690 
691     if( status_speed & 0x400 )
692     {
693         temp_speed = status_speed & IEEE_SPEED_MASK;
694 
695         if( temp_speed == IEEE_SPEED_1000 )
696         {
697             return 1000;
698         }
699         else if( temp_speed == IEEE_SPEED_100 )
700         {
701             return 100;
702         }
703         else
704         {
705             return 10;
706         }
707     }
708 
709     return XST_FAILURE;
710 }
711 
712 /* Here is a XEmacPs_PhyRead() that returns the value of a register. */
XEmacPs_PhyRead2(XEmacPs * InstancePtr,u32 PhyAddress,u32 RegisterNum)713 static uint16_t XEmacPs_PhyRead2( XEmacPs * InstancePtr,
714                                   u32 PhyAddress,
715                                   u32 RegisterNum )
716 {
717     LONG lResult;
718     uint16_t usReturn = 0U;
719 
720     lResult = XEmacPs_PhyRead( InstancePtr, PhyAddress, RegisterNum, &( usReturn ) );
721 
722     if( lResult != ( LONG ) ( XST_SUCCESS ) )
723     {
724         usReturn = 0U;
725     }
726 
727     return usReturn;
728 }
729 
730 static uint32_t ar8035CheckStatus( XEmacPs * xemacpsp,
731                                    uint32_t phy_addr );
732 
prvSET_AR803x_TX_Timing(XEmacPs * xemacpsp,uint32_t phy_addr)733 static void prvSET_AR803x_TX_Timing( XEmacPs * xemacpsp,
734                                      uint32_t phy_addr )
735 {
736 /*
737  *  rgmii_tx_clk_dly: tx clock delay control bit:
738  *  1 =  rgmii tx clock delay enable  <<= this option
739  *  0 =  rgmii tx clock delay disable.
740  *
741  *  Gtx_dly_val: select the delay of gtx_clk.
742  *  00:0.25ns
743  *  01:1.3ns  <<= this option
744  *  10:2.4ns
745  *  11:3.4ns
746  */
747     prvAR803x_debug_reg_write( xemacpsp, phy_addr, 0x5, 0x2d47 );
748     prvAR803x_debug_reg_write( xemacpsp, phy_addr, 0xb, 0xbc20 );
749 }
750 
get_AR8035_phy_speed(XEmacPs * xemacpsp,uint32_t phy_addr)751 static uint32_t get_AR8035_phy_speed( XEmacPs * xemacpsp,
752                                       uint32_t phy_addr )
753 {
754     uint32_t timeout_counter = 0;
755 
756     /*Reset PHY transceiver */
757     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, IEEE_CTRL_RESET_MASK );
758 
759     /*Wait for the reset to complete */
760     while( ( XEmacPs_PhyRead2( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET ) & IEEE_CTRL_RESET_MASK ) != 0U )
761     {
762     }
763 
764     /*Basic mode control register */
765     /* IEEE_CTRL_LINKSPEED_100M,  also known as 'AR8035_BMCR_SPEED_SEL_LSB' */
766     /* IEEE_STAT_1GBPS_EXTENSIONS also known as: AR8035_BMCR_DUPLEX_MODE' */
767     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, IEEE_CTRL_LINKSPEED_100M |
768                       IEEE_CTRL_AUTONEGOTIATE_ENABLE | IEEE_STAT_1GBPS_EXTENSIONS );
769 
770 #define AR8035_ANAR_SELECTOR_DEFAULT    0x0001
771 
772     /*Auto-negotiation advertisement register */
773     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
774                       IEEE_CTRL_AUTONEGOTIATE_ENABLE |
775                       IEEE_ASYMMETRIC_PAUSE_MASK |
776                       IEEE_PAUSE_MASK |
777                       ADVERTISE_100FULL |
778                       ADVERTISE_100HALF |
779                       ADVERTISE_10FULL |
780                       ADVERTISE_10HALF |
781                       AR8035_ANAR_SELECTOR_DEFAULT );
782 
783     /*1000 BASE-T control register */
784     XEmacPs_PhyWrite( xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, ADVERTISE_1000FULL );
785 
786 #define AR8035_FUNC_CTRL                          0x10
787 #define AR8035_FUNC_CTRL_ASSERT_CRS_ON_TX         0x0800
788 #define AR8035_FUNC_CTRL_MDIX_MODE                0x0060
789 #define AR8035_FUNC_CTRL_MDIX_MODE_MANUAL_MDI     0x0000
790 #define AR8035_FUNC_CTRL_MDIX_MODE_MANUAL_MDIX    0x0020
791 #define AR8035_FUNC_CTRL_MDIX_MODE_AUTO           0x0060
792 #define AR8035_FUNC_CTRL_SQE_TEST                 0x0004
793 #define AR8035_FUNC_CTRL_POLARITY_REVERSAL        0x0002
794 #define AR8035_FUNC_CTRL_JABBER_DIS               0x0001
795 
796     /*Function control register */
797     XEmacPs_PhyWrite( xemacpsp, phy_addr, AR8035_FUNC_CTRL,
798                       AR8035_FUNC_CTRL_ASSERT_CRS_ON_TX | AR8035_FUNC_CTRL_MDIX_MODE_AUTO |
799                       AR8035_FUNC_CTRL_POLARITY_REVERSAL );
800 
801     /*Dump PHY registers for debugging purpose */
802 /*	ar8035DumpPhyReg(interface); */
803 
804 #define AR8035_INT_EN                     0x12
805 #define AR8035_INT_STATUS_LINK_FAIL       0x0800
806 #define AR8035_INT_STATUS_LINK_SUCCESS    0x0400
807 
808     /*The PHY will generate interrupts when link status changes are detected */
809     XEmacPs_PhyWrite( xemacpsp, phy_addr, AR8035_INT_EN, AR8035_INT_STATUS_LINK_FAIL |
810                       AR8035_INT_STATUS_LINK_SUCCESS );
811 
812     while( pdTRUE )
813     {
814         uint32_t status;
815         my_sleep( 1 );
816 
817         timeout_counter++;
818 
819         if( timeout_counter == 30 )
820         {
821             FreeRTOS_printf( ( "Auto negotiation error \n" ) );
822             return XST_FAILURE;
823         }
824 
825         status = ar8035CheckStatus( xemacpsp, phy_addr );
826 
827         if( status > 10 )
828         {
829             prvSET_AR803x_TX_Timing( xemacpsp, phy_addr );
830             return status;
831         }
832     }
833 }
834 
ar8035Tick(XEmacPs * xemacpsp,uint32_t phy_addr)835 static void ar8035Tick( XEmacPs * xemacpsp,
836                         uint32_t phy_addr )
837 {
838     uint16_t value;
839     BaseType_t linkState;
840 
841     /*Read basic status register */
842     value = XEmacPs_PhyRead2( xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET );
843     /*Retrieve current link state */
844     linkState = ( value & IEEE_STAT_LINK_STATUS ) ? TRUE : FALSE;
845 }
846 
847 #define AR803X_DEBUG_ADDR    0x1D
848 #define AR803X_DEBUG_DATA    0x1E
prvAR803x_debug_reg_read(XEmacPs * xemacpsp,uint32_t phy_addr,u16 reg)849 static uint16_t prvAR803x_debug_reg_read( XEmacPs * xemacpsp,
850                                           uint32_t phy_addr,
851                                           u16 reg )
852 {
853     XEmacPs_PhyWrite( xemacpsp, phy_addr, AR803X_DEBUG_ADDR, reg );
854 
855     return XEmacPs_PhyRead2( xemacpsp, phy_addr, AR803X_DEBUG_DATA );
856 }
857 
prvAR803x_debug_reg_write(XEmacPs * xemacpsp,uint32_t phy_addr,u16 reg,u16 value)858 static uint16_t prvAR803x_debug_reg_write( XEmacPs * xemacpsp,
859                                            uint32_t phy_addr,
860                                            u16 reg,
861                                            u16 value )
862 {
863     XEmacPs_PhyWrite( xemacpsp, phy_addr, AR803X_DEBUG_ADDR, reg );
864 
865     return XEmacPs_PhyWrite( xemacpsp, phy_addr, AR803X_DEBUG_DATA, value );
866 }
867 
prvAR803x_debug_reg_mask(XEmacPs * xemacpsp,uint32_t phy_addr,u16 reg,u16 clear,u16 set)868 static int prvAR803x_debug_reg_mask( XEmacPs * xemacpsp,
869                                      uint32_t phy_addr,
870                                      u16 reg,
871                                      u16 clear,
872                                      u16 set )
873 {
874     u16 val;
875     int ret;
876 
877     ret = prvAR803x_debug_reg_read( xemacpsp, phy_addr, reg );
878 
879     if( ret < 0 )
880     {
881         return ret;
882     }
883 
884     val = ret & 0xffff;
885     val &= ~clear;
886     val |= set;
887 
888     return XEmacPs_PhyWrite( xemacpsp, phy_addr, AR803X_DEBUG_DATA, val );
889 }
890 
ar8035CheckStatus(XEmacPs * xemacpsp,uint32_t phy_addr)891 static uint32_t ar8035CheckStatus( XEmacPs * xemacpsp,
892                                    uint32_t phy_addr )
893 {
894     uint16_t status;
895     uint32_t linkSpeed = 0U;
896     BaseType_t linkState = pdFALSE;
897 
898     /*Read status register to acknowledge the interrupt */
899     status = XEmacPs_PhyRead2( xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2 );
900 
901 #define AR8035_INT_STATUS_LINK_FAIL       0x0800
902 #define AR8035_INT_STATUS_LINK_SUCCESS    0x0400
903 
904     /*Link status change? */
905     if( status & ( AR8035_INT_STATUS_LINK_FAIL | AR8035_INT_STATUS_LINK_SUCCESS ) )
906     {
907         /*Read PHY status register */
908         status = XEmacPs_PhyRead2( xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG );
909 
910 #define AR8035_PHY_STATUS_LINK    0x0400
911 
912         /*Link is up? */
913         if( status & AR8035_PHY_STATUS_LINK )
914         {
915 #define AR8035_PHY_STATUS_SPEED             0xC000
916 #define AR8035_PHY_STATUS_SPEED_10MBPS      0x0000
917 #define AR8035_PHY_STATUS_SPEED_100MBPS     0x4000
918 #define AR8035_PHY_STATUS_SPEED_1000MBPS    0x8000
919 
920             /*Check current speed */
921             switch( status & AR8035_PHY_STATUS_SPEED )
922             {
923                 /*10BASE-T */
924                 case AR8035_PHY_STATUS_SPEED_10MBPS:
925                     linkSpeed = 10;
926                     break;
927 
928                 /*100BASE-TX */
929                 case AR8035_PHY_STATUS_SPEED_100MBPS:
930                     linkSpeed = 100;
931                     break;
932 
933                 /*1000BASE-T */
934                 case AR8035_PHY_STATUS_SPEED_1000MBPS:
935                     linkSpeed = 1000;
936                     break;
937 
938                 /*Unknown speed */
939                 default:
940                     /*Debug message */
941                     FreeRTOS_printf( ( "Invalid speed ( status %04X )\n", status ) );
942                     break;
943             }
944 
945 #define AR8035_PHY_STATUS_DUPLEX    0x2000
946 
947             /*Check current duplex mode */
948             if( status & AR8035_PHY_STATUS_DUPLEX )
949             {
950                 FreeRTOS_printf( ( "Full duplex\n" ) );
951             }
952             else
953             {
954                 FreeRTOS_printf( ( "Half duplex\n" ) );
955             }
956 
957             /*Update link state */
958             linkState = TRUE;
959 
960             /*Adjust MAC configuration parameters for proper operation */
961             /*interface->nicDriver->updateMacConfig(interface); */
962         }
963         else
964         {
965             /*Update link state */
966             linkState = FALSE;
967         }
968 
969         /*Process link state change event */
970 /*		nicNotifyLinkChange(interface); */
971     }
972 
973     return linkSpeed;
974 }
975 
976 
pcGetPHIName(uint16_t usID)977 static const char * pcGetPHIName( uint16_t usID )
978 {
979     const char * pcReturn = "";
980     static char pcName[ 16 ];
981 
982     switch( usID )
983     {
984         case PHY_TI_IDENTIFIER:
985             pcReturn = "TI_dp83869hm";
986             break;
987 
988         case PHY_REALTEK_IDENTIFIER:
989             pcReturn = "Realtek RTL8212";
990             break;
991 
992         case PHY_AR8035_IDENTIFIER:
993             pcReturn = "Atheros_ar8035";
994             break;
995 
996         case PHY_MARVELL_IDENTIFIER:
997             pcReturn = "Marvell_88E1512";
998             break;
999 
1000         default:
1001             snprintf( pcName, sizeof pcName, "Unkkwn PHY %04X", usID );
1002             pcReturn = pcName;
1003             break;
1004     }
1005 
1006     return pcReturn;
1007 }
1008 
get_IEEE_phy_speed_US(XEmacPs * xemacpsp,uint32_t phy_addr)1009 static uint32_t get_IEEE_phy_speed_US( XEmacPs * xemacpsp,
1010                                        uint32_t phy_addr )
1011 {
1012     uint16_t phy_identity;
1013     uint32_t RetStatus;
1014 
1015     XEmacPs_PhyRead( xemacpsp, phy_addr, PHY_IDENTIFIER_1_REG,
1016                      &phy_identity );
1017 
1018     FreeRTOS_printf( ( "Start %s PHY autonegotiation. ID = 0x%04X\n", pcGetPHIName( phy_identity ), phy_identity ) );
1019 
1020     switch( phy_identity )
1021     {
1022         case PHY_TI_IDENTIFIER:
1023             RetStatus = get_TI_phy_speed( xemacpsp, phy_addr );
1024             break;
1025 
1026         case PHY_REALTEK_IDENTIFIER:
1027             RetStatus = get_Realtek_phy_speed( xemacpsp, phy_addr );
1028             break;
1029 
1030         case PHY_MARVELL_IDENTIFIER:
1031             RetStatus = get_Marvell_phy_speed( xemacpsp, phy_addr );
1032             break;
1033 
1034         case PHY_AR8035_IDENTIFIER:
1035             RetStatus = get_AR8035_phy_speed( xemacpsp, phy_addr );
1036             /* RetStatus = get_Marvell_phy_speed(xemacpsp, phy_addr); */
1037             /* RetStatus = get_Realtek_phy_speed(xemacpsp, phy_addr); */
1038             prvSET_AR803x_TX_Timing( xemacpsp, phy_addr );
1039             break;
1040 
1041         default:
1042             FreeRTOS_printf( ( "Don't know how to handle PHY ID %04X\n", phy_identity ) );
1043             RetStatus = XST_FAILURE;
1044             break;
1045     }
1046 
1047     return RetStatus;
1048 }
1049 
SetUpSLCRDivisors(u32 mac_baseaddr,s32 speed)1050 static void SetUpSLCRDivisors( u32 mac_baseaddr,
1051                                s32 speed )
1052 {
1053     volatile u32 slcrBaseAddress;
1054     u32 SlcrDiv0 = 0;
1055     u32 SlcrDiv1 = 0;
1056     u32 SlcrTxClkCntrl;
1057     u32 gigeversion;
1058     volatile u32 CrlApbBaseAddr;
1059     u32 CrlApbDiv0 = 0;
1060     u32 CrlApbDiv1 = 0;
1061     u32 CrlApbGemCtrl;
1062 
1063     gigeversion = ( ( Xil_In32( mac_baseaddr + 0xFC ) ) >> 16 ) & 0xFFF;
1064 
1065     if( gigeversion == 2 )
1066     {
1067         *( volatile u32 * ) ( SLCR_UNLOCK_ADDR ) = SLCR_UNLOCK_KEY_VALUE;
1068 
1069         if( mac_baseaddr == ZYNQ_EMACPS_0_BASEADDR )
1070         {
1071             slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
1072         }
1073         else
1074         {
1075             slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
1076         }
1077 
1078         if( ( *( volatile u32 * ) ( UINTPTR ) ( slcrBaseAddress ) ) &
1079             SLCR_GEM_SRCSEL_EMIO )
1080         {
1081             return;
1082         }
1083 
1084         if( speed == 1000 )
1085         {
1086             if( mac_baseaddr == XPAR_XEMACPS_0_BASEADDR )
1087             {
1088                 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
1089                     SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
1090                     SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
1091                 #endif
1092             }
1093             else
1094             {
1095                 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
1096                     SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
1097                     SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
1098                 #endif
1099             }
1100         }
1101         else if( speed == 100 )
1102         {
1103             if( mac_baseaddr == XPAR_XEMACPS_0_BASEADDR )
1104             {
1105                 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
1106                     SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
1107                     SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
1108                 #endif
1109             }
1110             else
1111             {
1112                 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
1113                     SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
1114                     SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
1115                 #endif
1116             }
1117         }
1118         else
1119         {
1120             if( mac_baseaddr == XPAR_XEMACPS_0_BASEADDR )
1121             {
1122                 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
1123                     SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
1124                     SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
1125                 #endif
1126             }
1127             else
1128             {
1129                 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
1130                     SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
1131                     SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
1132                 #endif
1133             }
1134         }
1135 
1136         if( ( SlcrDiv0 != 0 ) && ( SlcrDiv1 != 0 ) )
1137         {
1138             SlcrTxClkCntrl = *( volatile u32 * ) ( UINTPTR ) ( slcrBaseAddress );
1139             SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
1140             SlcrTxClkCntrl |= ( SlcrDiv1 << 20 );
1141             SlcrTxClkCntrl |= ( SlcrDiv0 << 8 );
1142             *( volatile u32 * ) ( UINTPTR ) ( slcrBaseAddress ) = SlcrTxClkCntrl;
1143             *( volatile u32 * ) ( SLCR_LOCK_ADDR ) = SLCR_LOCK_KEY_VALUE;
1144         }
1145         else
1146         {
1147             FreeRTOS_printf( ( "Clock Divisors incorrect - Please check\n" ) );
1148         }
1149     }
1150     else if( gigeversion == GEM_VERSION_ZYNQMP )
1151     {
1152         /* Setup divisors in CRL_APB for Zynq Ultrascale+ MPSoC */
1153         if( mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR )
1154         {
1155             CrlApbBaseAddr = CRL_APB_GEM0_REF_CTRL;
1156         }
1157         else if( mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR )
1158         {
1159             CrlApbBaseAddr = CRL_APB_GEM1_REF_CTRL;
1160         }
1161         else if( mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR )
1162         {
1163             CrlApbBaseAddr = CRL_APB_GEM2_REF_CTRL;
1164         }
1165         else if( mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR )
1166         {
1167             CrlApbBaseAddr = CRL_APB_GEM3_REF_CTRL;
1168         }
1169 
1170         if( speed == 1000 )
1171         {
1172             if( mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR )
1173             {
1174                 #ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
1175                     CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
1176                     CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
1177                 #endif
1178             }
1179             else if( mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR )
1180             {
1181                 #ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
1182                     CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
1183                     CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
1184                 #endif
1185             }
1186             else if( mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR )
1187             {
1188                 #ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0
1189                     CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV0;
1190                     CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_1000MBPS_DIV1;
1191                 #endif
1192             }
1193             else if( mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR )
1194             {
1195                 #ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0
1196                     CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV0;
1197                     CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_1000MBPS_DIV1;
1198                 #endif
1199             }
1200         }
1201         else if( speed == 100 )
1202         {
1203             if( mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR )
1204             {
1205                 #ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
1206                     CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
1207                     CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
1208                 #endif
1209             }
1210             else if( mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR )
1211             {
1212                 #ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
1213                     CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
1214                     CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
1215                 #endif
1216             }
1217             else if( mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR )
1218             {
1219                 #ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0
1220                     CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV0;
1221                     CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_100MBPS_DIV1;
1222                 #endif
1223             }
1224             else if( mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR )
1225             {
1226                 #ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0
1227                     CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV0;
1228                     CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_100MBPS_DIV1;
1229                 #endif
1230             }
1231         }
1232         else
1233         {
1234             if( mac_baseaddr == ZYNQMP_EMACPS_0_BASEADDR )
1235             {
1236                 #ifdef XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
1237                     CrlApbDiv0 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
1238                     CrlApbDiv1 = XPAR_PSU_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
1239                 #endif
1240             }
1241             else if( mac_baseaddr == ZYNQMP_EMACPS_1_BASEADDR )
1242             {
1243                 #ifdef XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
1244                     CrlApbDiv0 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
1245                     CrlApbDiv1 = XPAR_PSU_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
1246                 #endif
1247             }
1248             else if( mac_baseaddr == ZYNQMP_EMACPS_2_BASEADDR )
1249             {
1250                 #ifdef XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0
1251                     CrlApbDiv0 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV0;
1252                     CrlApbDiv1 = XPAR_PSU_ETHERNET_2_ENET_SLCR_10MBPS_DIV1;
1253                 #endif
1254             }
1255             else if( mac_baseaddr == ZYNQMP_EMACPS_3_BASEADDR )
1256             {
1257                 #ifdef XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0
1258                     CrlApbDiv0 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV0;
1259                     CrlApbDiv1 = XPAR_PSU_ETHERNET_3_ENET_SLCR_10MBPS_DIV1;
1260                 #endif
1261             }
1262         }
1263 
1264         if( ( CrlApbDiv0 != 0 ) && ( CrlApbDiv1 != 0 ) )
1265         {
1266             #if EL1_NONSECURE
1267                 XSmc_OutVar RegRead;
1268                 RegRead = Xil_Smc( MMIO_READ_SMC_FID, ( u64 ) ( CrlApbBaseAddr ),
1269                                    0, 0, 0, 0, 0, 0 );
1270                 CrlApbGemCtrl = RegRead.Arg0 >> 32;
1271             #else
1272                 CrlApbGemCtrl = *( volatile u32 * ) ( UINTPTR ) ( CrlApbBaseAddr );
1273             #endif
1274             CrlApbGemCtrl &= ~CRL_APB_GEM_DIV0_MASK;
1275             CrlApbGemCtrl |= CrlApbDiv0 << CRL_APB_GEM_DIV0_SHIFT;
1276             CrlApbGemCtrl &= ~CRL_APB_GEM_DIV1_MASK;
1277             CrlApbGemCtrl |= CrlApbDiv1 << CRL_APB_GEM_DIV1_SHIFT;
1278             #if EL1_NONSECURE
1279                 Xil_Smc( MMIO_WRITE_SMC_FID, ( u64 ) ( CrlApbBaseAddr ) | ( ( u64 ) ( 0xFFFFFFFF ) << 32 ),
1280                          ( u64 ) CrlApbGemCtrl, 0, 0, 0, 0, 0 );
1281 
1282                 do
1283                 {
1284                     RegRead = Xil_Smc( MMIO_READ_SMC_FID, ( u64 ) ( CrlApbBaseAddr ),
1285                                        0, 0, 0, 0, 0, 0 );
1286                 } while( ( RegRead.Arg0 >> 32 ) != CrlApbGemCtrl );
1287             #else
1288                 *( volatile u32 * ) ( UINTPTR ) ( CrlApbBaseAddr ) = CrlApbGemCtrl;
1289             #endif
1290         }
1291         else
1292         {
1293             FreeRTOS_printf( ( "Clock Divisors incorrect - Please check\n" ) );
1294         }
1295     }
1296     else if( gigeversion == GEM_VERSION_VERSAL )
1297     {
1298         /* Setup divisors in CRL for Versal */
1299         if( mac_baseaddr == VERSAL_EMACPS_0_BASEADDR )
1300         {
1301             CrlApbBaseAddr = VERSAL_CRL_GEM0_REF_CTRL;
1302             #if EL1_NONSECURE
1303                 ClkId = CLK_GEM0_REF;
1304             #endif
1305         }
1306         else if( mac_baseaddr == VERSAL_EMACPS_1_BASEADDR )
1307         {
1308             CrlApbBaseAddr = VERSAL_CRL_GEM1_REF_CTRL;
1309             #if EL1_NONSECURE
1310                 ClkId = CLK_GEM1_REF;
1311             #endif
1312         }
1313 
1314         if( speed == 1000 )
1315         {
1316             if( mac_baseaddr == VERSAL_EMACPS_0_BASEADDR )
1317             {
1318                 #ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
1319                     CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
1320                 #endif
1321             }
1322             else if( mac_baseaddr == VERSAL_EMACPS_1_BASEADDR )
1323             {
1324                 #ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
1325                     CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
1326                 #endif
1327             }
1328         }
1329         else if( speed == 100 )
1330         {
1331             if( mac_baseaddr == VERSAL_EMACPS_0_BASEADDR )
1332             {
1333                 #ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
1334                     CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
1335                 #endif
1336             }
1337             else if( mac_baseaddr == VERSAL_EMACPS_1_BASEADDR )
1338             {
1339                 #ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
1340                     CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
1341                 #endif
1342             }
1343         }
1344         else
1345         {
1346             if( mac_baseaddr == VERSAL_EMACPS_0_BASEADDR )
1347             {
1348                 #ifdef XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
1349                     CrlApbDiv0 = XPAR_PSV_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
1350                 #endif
1351             }
1352             else if( mac_baseaddr == VERSAL_EMACPS_1_BASEADDR )
1353             {
1354                 #ifdef XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
1355                     CrlApbDiv0 = XPAR_PSV_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
1356                 #endif
1357             }
1358         }
1359 
1360         if( CrlApbDiv0 != 0 )
1361         {
1362             #if EL1_NONSECURE
1363                 Xil_Smc( PM_SET_DIVIDER_SMC_FID, ( ( ( u64 ) CrlApbDiv0 << 32 ) | ClkId ), 0, 0, 0, 0, 0, 0 );
1364             #else
1365                 CrlApbGemCtrl = Xil_In32( ( UINTPTR ) CrlApbBaseAddr );
1366                 CrlApbGemCtrl &= ~VERSAL_CRL_GEM_DIV_MASK;
1367                 CrlApbGemCtrl |= CrlApbDiv0 << VERSAL_CRL_APB_GEM_DIV_SHIFT;
1368 
1369                 Xil_Out32( ( UINTPTR ) CrlApbBaseAddr, CrlApbGemCtrl );
1370             #endif
1371         }
1372         else
1373         {
1374             FreeRTOS_printf( ( "Clock Divisors incorrect - Please check\n" ) );
1375         }
1376     }
1377 }
1378 
Phy_Setup_US(XEmacPs * xemacpsp,u32 phy_addr)1379 u32 Phy_Setup_US( XEmacPs * xemacpsp,
1380                   u32 phy_addr )
1381 {
1382     u32 link_speed = 0;
1383     u32 conv_present = 0;
1384     u32 convspeeddupsetting = 0;
1385     u32 convphyaddr = 0;
1386 
1387     #ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR
1388         convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
1389         conv_present = 1;
1390     #else
1391         #ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR
1392             convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
1393             conv_present = 1;
1394         #endif
1395     #endif
1396 
1397     #ifdef  ipconfigNIC_LINKSPEED_AUTODETECT
1398         link_speed = get_IEEE_phy_speed_US( xemacpsp, phy_addr );
1399 
1400         if( link_speed == 1000 )
1401         {
1402             SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 1000 );
1403             convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
1404         }
1405         else if( link_speed == 100 )
1406         {
1407             SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 100 );
1408             convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
1409         }
1410         else if( link_speed != XST_FAILURE )
1411         {
1412             SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 10 );
1413             convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
1414         }
1415         else
1416         {
1417             FreeRTOS_printf( ( "Phy setup error \n" ) );
1418             return XST_FAILURE;
1419         }
1420     #elif   defined( ipconfigNIC_LINKSPEED1000 )
1421         SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 1000, , phy_addr );
1422         link_speed = 1000;
1423         configure_IEEE_phy_speed_US( xemacpsp, link_speed );
1424         convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
1425         my_sleep( 1 );
1426     #elif   defined( ipconfigNIC_LINKSPEED100 )
1427         SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 100 );
1428         link_speed = 100;
1429         configure_IEEE_phy_speed_US( xemacpsp, link_speed, phy_addr );
1430         convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
1431         my_sleep( 1 );
1432     #elif   defined( ipconfigNIC_LINKSPEED10 )
1433         SetUpSLCRDivisors( xemacpsp->Config.BaseAddress, 10 );
1434         link_speed = 10;
1435         configure_IEEE_phy_speed_US( xemacpsp, link_speed, , phy_addr );
1436         convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
1437         my_sleep( 1 );
1438     #endif /* ifdef  ipconfigNIC_LINKSPEED_AUTODETECT */
1439 
1440     if( conv_present )
1441     {
1442         XEmacPs_PhyWrite( xemacpsp, convphyaddr,
1443                           XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting );
1444     }
1445 
1446     FreeRTOS_printf( ( "link speed: %d\n", link_speed ) );
1447     return link_speed;
1448 }
1449