]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c
742ff8b96665c9797e7fc4d6625c0728d48d7e30
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / Zynq / x_emacpsif_physpeed.c
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 "Zynq/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 int phy_detected = 0;
75
76 /*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
77  *** to run it on a PEEP board
78  ***/
79
80 /* Advertisement control register. */
81 #define ADVERTISE_10HALF                0x0020  /* Try for 10mbps half-duplex  */
82 #define ADVERTISE_10FULL                0x0040  /* Try for 10mbps full-duplex  */
83 #define ADVERTISE_100HALF               0x0080  /* Try for 100mbps half-duplex */
84 #define ADVERTISE_100FULL               0x0100  /* Try for 100mbps full-duplex */
85
86 #define ADVERTISE_100_AND_10    (ADVERTISE_10FULL | ADVERTISE_100FULL | \
87                                                                 ADVERTISE_10HALF | ADVERTISE_100HALF)
88 #define ADVERTISE_100                   (ADVERTISE_100FULL | ADVERTISE_100HALF)
89 #define ADVERTISE_10                    (ADVERTISE_10FULL | ADVERTISE_10HALF)
90
91 #define ADVERTISE_1000                  0x0300
92
93
94 //#define PHY_REG_00_BMCR            0x00 // Basic mode control register
95 //#define PHY_REG_01_BMSR            0x01 // Basic mode status register
96 //#define PHY_REG_02_PHYSID1         0x02 // PHYS ID 1
97 //#define PHY_REG_03_PHYSID2         0x03 // PHYS ID 2
98 //#define PHY_REG_04_ADVERTISE       0x04 // Advertisement control reg
99
100 #define IEEE_CONTROL_REG_OFFSET                         0
101 #define IEEE_STATUS_REG_OFFSET                          1
102 #define IEEE_AUTONEGO_ADVERTISE_REG                     4
103 #define IEEE_PARTNER_ABILITIES_1_REG_OFFSET     5
104 #define IEEE_1000_ADVERTISE_REG_OFFSET          9
105 #define IEEE_PARTNER_ABILITIES_3_REG_OFFSET     10
106 #define IEEE_COPPER_SPECIFIC_CONTROL_REG        16
107 #define IEEE_SPECIFIC_STATUS_REG                        17
108 #define IEEE_COPPER_SPECIFIC_STATUS_REG_2       19
109 #define IEEE_CONTROL_REG_MAC                            21
110 #define IEEE_PAGE_ADDRESS_REGISTER                      22
111
112
113 #define IEEE_CTRL_1GBPS_LINKSPEED_MASK          0x2040
114 #define IEEE_CTRL_LINKSPEED_MASK                        0x0040
115 #define IEEE_CTRL_LINKSPEED_1000M                       0x0040
116 #define IEEE_CTRL_LINKSPEED_100M                        0x2000
117 #define IEEE_CTRL_LINKSPEED_10M                         0x0000
118 #define IEEE_CTRL_RESET_MASK                            0x8000
119 #define IEEE_CTRL_AUTONEGOTIATE_ENABLE          0x1000
120 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
121 #define IEEE_CTRL_RESET                         0x9140
122 #define IEEE_CTRL_ISOLATE_DISABLE               0xFBFF
123 #endif
124 #define IEEE_STAT_AUTONEGOTIATE_CAPABLE         0x0008
125 #define IEEE_STAT_AUTONEGOTIATE_COMPLETE        0x0020
126 #define IEEE_STAT_AUTONEGOTIATE_RESTART         0x0200
127 #define IEEE_STAT_1GBPS_EXTENSIONS                      0x0100
128 #define IEEE_AN1_ABILITY_MASK                           0x1FE0
129 #define IEEE_AN3_ABILITY_MASK_1GBPS                     0x0C00
130 #define IEEE_AN1_ABILITY_MASK_100MBPS           0x0380
131 #define IEEE_AN1_ABILITY_MASK_10MBPS            0x0060
132 #define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK      0x0030
133
134 #define IEEE_ASYMMETRIC_PAUSE_MASK                      0x0800
135 #define IEEE_PAUSE_MASK                                         0x0400
136 #define IEEE_AUTONEG_ERROR_MASK                         0x8000
137
138 #define PHY_DETECT_REG  1
139 #define PHY_DETECT_MASK 0x1808
140
141 #define XEMACPS_GMII2RGMII_SPEED1000_FD         0x140
142 #define XEMACPS_GMII2RGMII_SPEED100_FD          0x2100
143 #define XEMACPS_GMII2RGMII_SPEED10_FD           0x100
144 #define XEMACPS_GMII2RGMII_REG_NUM                      0x10
145
146 /* Frequency setting */
147 #define SLCR_LOCK_ADDR                  (XPS_SYS_CTRL_BASEADDR + 0x4)
148 #define SLCR_UNLOCK_ADDR                (XPS_SYS_CTRL_BASEADDR + 0x8)
149 #define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140)
150 #define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144)
151 #ifdef PEEP
152 #define SLCR_GEM_10M_CLK_CTRL_VALUE             0x00103031
153 #define SLCR_GEM_100M_CLK_CTRL_VALUE    0x00103001
154 #define SLCR_GEM_1G_CLK_CTRL_VALUE              0x00103011
155 #endif
156 #define SLCR_LOCK_KEY_VALUE                     0x767B
157 #define SLCR_UNLOCK_KEY_VALUE                   0xDF0D
158 #define SLCR_ADDR_GEM_RST_CTRL                  (XPS_SYS_CTRL_BASEADDR + 0x214)
159 #define EMACPS_SLCR_DIV_MASK                    0xFC0FC0FF
160
161 #define EMAC0_BASE_ADDRESS                              0xE000B000
162 #define EMAC1_BASE_ADDRESS                              0xE000C000
163
164 static int detect_phy(XEmacPs *xemacpsp)
165 {
166         u16 phy_reg;
167         u32 phy_addr;
168
169         for (phy_addr = 31; phy_addr > 0; phy_addr--) {
170                 XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,
171                                                         &phy_reg);
172
173                 if ((phy_reg != 0xFFFF) &&
174                         ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {
175                         /* Found a valid PHY address */
176                         FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected at address %d.\r\n",
177                                                                                                                                         phy_addr));
178                         FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected.\n" ) );
179                         phy_detected = phy_addr;
180                         return phy_addr;
181                 }
182         }
183
184         FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected.  Assuming a PHY at address 0\n" ) );
185
186         /* default to zero */
187         return 0;
188 }
189
190 #ifdef PEEP
191 unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
192 {
193
194         u16 control;
195         u16 status;
196         u16 partner_capabilities;
197         u16 partner_capabilities_1000;
198         u16 phylinkspeed;
199         u32 phy_addr = detect_phy(xemacpsp);
200
201         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
202                                                                                                                         ADVERTISE_1000);
203         /* Advertise PHY speed of 100 and 10 Mbps */
204         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
205                                                                                                         ADVERTISE_100_AND_10);
206
207         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
208                                                                                                                                 &control);
209         control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |
210                                         IEEE_STAT_AUTONEGOTIATE_RESTART);
211
212         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
213
214         /* Read PHY control and status registers is successful. */
215         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
216         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
217
218         if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &
219                                         IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {
220
221                 while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
222                         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
223                                                                                                                                 &status);
224                 }
225
226                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,
227                                                                                                                         &partner_capabilities);
228
229                 if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
230                         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,
231                                                                                                                 &partner_capabilities_1000);
232                         if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS)
233                                 return 1000;
234                 }
235
236                 if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)
237                         return 100;
238                 if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)
239                         return 10;
240
241                 xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n",
242                                 __FUNCTION__);
243                 return 10;
244
245         } else {
246
247                 /* Update TEMAC speed accordingly */
248                 if (status & IEEE_STAT_1GBPS_EXTENSIONS) {
249                         /* Get commanded link speed */
250                         phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;
251
252                         switch (phylinkspeed) {
253                                 case (IEEE_CTRL_LINKSPEED_1000M):
254                                         return 1000;
255                                 case (IEEE_CTRL_LINKSPEED_100M):
256                                         return 100;
257                                 case (IEEE_CTRL_LINKSPEED_10M):
258                                         return 10;
259                                 default:
260                                         xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n",
261                                                         __FUNCTION__, phylinkspeed);
262                                         return 10;
263                         }
264
265                 } else {
266
267                         return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;
268
269                 }
270         }
271 }
272
273 #else /* Zynq */
274 unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)
275 {
276         u16 temp;
277         u16 control;
278         u16 status;
279         u16 partner_capabilities;
280 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
281         u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;
282 #else
283         u32 phy_addr = detect_phy(xemacpsp);
284 #endif
285         xil_printf("Start PHY autonegotiation \r\n");
286
287 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
288 #else
289         XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
290         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
291         control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
292         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
293
294         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
295
296         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
297         control |= IEEE_ASYMMETRIC_PAUSE_MASK;
298         control |= IEEE_PAUSE_MASK;
299         control |= ADVERTISE_100;
300         control |= ADVERTISE_10;
301         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
302
303         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
304                                                                                                                                         &control);
305         control |= ADVERTISE_1000;
306         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
307                                                                                                                                         control);
308
309         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
310         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
311                                                                                                                                 &control);
312         control |= (7 << 12);   /* max number of gigabit attempts */
313         control |= (1 << 11);   /* enable downshift */
314         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,
315                                                                                                                                 control);
316 #endif
317         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
318         control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;
319         control |= IEEE_STAT_AUTONEGOTIATE_RESTART;
320 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
321     control &= IEEE_CTRL_ISOLATE_DISABLE;
322 #endif
323
324         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
325
326
327 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
328 #else
329         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
330         control |= IEEE_CTRL_RESET_MASK;
331         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);
332
333         while (1) {
334                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
335                 if (control & IEEE_CTRL_RESET_MASK)
336                         continue;
337                 else
338                         break;
339         }
340 #endif
341         xil_printf("Waiting for PHY to complete autonegotiation.\r\n");
342
343         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
344         while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {
345                 sleep(1);
346 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
347 #else
348                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,
349                                                                                                                                         &temp);
350                 if (temp & IEEE_AUTONEG_ERROR_MASK) {
351                         xil_printf("Auto negotiation error \r\n");
352                 }
353 #endif
354                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,
355                                                                                                                                 &status);
356                 }
357
358         xil_printf("autonegotiation complete \r\n");
359
360 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
361 #else
362         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);
363 #endif
364
365 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1
366         xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");
367         XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
368         while(!(temp & 0x8000)) {
369                 XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);
370         }
371         if((temp & 0x0C00) == 0x0800) {
372                 XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
373                 return 1000;
374         }
375         else if((temp & 0x0C00) == 0x0400) {
376                 XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
377                 return 100;
378         }
379         else if((temp & 0x0C00) == 0x0000) {
380                 XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
381                 return 10;
382         } else {
383                 xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\r\n");
384                 XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);
385                 XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);
386                 return 10;
387         }
388 #else
389         if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */
390                 return 1000;
391         else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */
392                 return 100;
393         else                                    /* 10Mbps */
394                 return 10;
395 #endif
396 }
397 #endif
398
399 unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)
400 {
401         u16 control;
402         u32 phy_addr = detect_phy(xemacpsp);
403
404         XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);
405         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);
406         control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;
407         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);
408
409         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);
410
411         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);
412         control |= IEEE_ASYMMETRIC_PAUSE_MASK;
413         control |= IEEE_PAUSE_MASK;
414         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);
415
416         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);
417         control &= ~IEEE_CTRL_LINKSPEED_1000M;
418         control &= ~IEEE_CTRL_LINKSPEED_100M;
419         control &= ~IEEE_CTRL_LINKSPEED_10M;
420
421         if (speed == 1000) {
422                 control |= IEEE_CTRL_LINKSPEED_1000M;
423         }
424
425         else if (speed == 100) {
426                 control |= IEEE_CTRL_LINKSPEED_100M;
427                 /* Dont advertise PHY speed of 1000 Mbps */
428                 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);
429                 /* Dont advertise PHY speed of 10 Mbps */
430                 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
431                                                                                                                                 ADVERTISE_100);
432         }
433
434         else if (speed == 10) {
435                 control |= IEEE_CTRL_LINKSPEED_10M;
436                 /* Dont advertise PHY speed of 1000 Mbps */
437                 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,
438                                                                                                                                                         0);
439                 /* Dont advertise PHY speed of 100 Mbps */
440                 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,
441                                                                                                                                 ADVERTISE_10);
442         }
443
444         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,
445                                                                                         control | IEEE_CTRL_RESET_MASK);
446         {
447                 volatile int wait;
448                 for (wait=0; wait < 100000; wait++);
449         }
450         return 0;
451 }
452
453 static void SetUpSLCRDivisors(int mac_baseaddr, int speed)
454 {
455         volatile u32 slcrBaseAddress;
456 #ifndef PEEP
457         u32 SlcrDiv0;
458         u32 SlcrDiv1=0;
459         u32 SlcrTxClkCntrl;
460 #endif
461
462         *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;
463
464         if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
465                 slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;
466         } else {
467                 slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;
468         }
469 #ifdef PEEP
470         if (speed == 1000) {
471                 *(volatile unsigned int *)(slcrBaseAddress) =
472                                                                                         SLCR_GEM_1G_CLK_CTRL_VALUE;
473         } else if (speed == 100) {
474                 *(volatile unsigned int *)(slcrBaseAddress) =
475                                                                                         SLCR_GEM_100M_CLK_CTRL_VALUE;
476         } else {
477                 *(volatile unsigned int *)(slcrBaseAddress) =
478                                                                                         SLCR_GEM_10M_CLK_CTRL_VALUE;
479         }
480 #else
481         if (speed == 1000) {
482                 if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
483 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0
484                         SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;
485                         SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;
486 #endif
487                 } else {
488 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0
489                         SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;
490                         SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;
491 #endif
492                 }
493         } else if (speed == 100) {
494                 if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
495 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0
496                         SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;
497                         SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;
498 #endif
499                 } else {
500 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0
501                         SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;
502                         SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;
503 #endif
504                 }
505         } else {
506                 if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {
507 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0
508                         SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;
509                         SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;
510 #endif
511                 } else {
512 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0
513                         SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;
514                         SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;
515 #endif
516                 }
517         }
518         SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress);
519         SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;
520         SlcrTxClkCntrl |= (SlcrDiv1 << 20);
521         SlcrTxClkCntrl |= (SlcrDiv0 << 8);
522         *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;
523 #endif
524         *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;
525         return;
526 }
527
528
529 unsigned link_speed;
530 unsigned Phy_Setup (XEmacPs *xemacpsp)
531 {
532         unsigned long conv_present = 0;
533         unsigned long convspeeddupsetting = 0;
534         unsigned long convphyaddr = 0;
535
536 #ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR
537         convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;
538         conv_present = 1;
539 #else
540 #ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR
541         convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;
542         conv_present = 1;
543 #endif
544 #endif
545
546 #ifdef  ipconfigNIC_LINKSPEED_AUTODETECT
547         link_speed = get_IEEE_phy_speed(xemacpsp);
548         if (link_speed == 1000) {
549                 SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
550                 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
551         } else if (link_speed == 100) {
552                 SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
553                 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
554         } else {
555                 SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
556                 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
557         }
558 #elif   defined(ipconfigNIC_LINKSPEED1000)
559         SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);
560         link_speed = 1000;
561         configure_IEEE_phy_speed(xemacpsp, link_speed);
562         convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;
563         sleep(1);
564 #elif   defined(ipconfigNIC_LINKSPEED100)
565         SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);
566         link_speed = 100;
567         configure_IEEE_phy_speed(xemacpsp, link_speed);
568         convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;
569         sleep(1);
570 #elif   defined(ipconfigNIC_LINKSPEED10)
571         SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);
572         link_speed = 10;
573         configure_IEEE_phy_speed(xemacpsp, link_speed);
574         convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;
575         sleep(1);
576 #endif
577         if (conv_present) {
578                 XEmacPs_PhyWrite(xemacpsp, convphyaddr,
579                 XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);
580         }
581
582         xil_printf("link speed: %d\r\n", link_speed);
583         return link_speed;
584 }
585