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