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