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