]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c
Sync FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP with the version in GitHub at (23665258ca...
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / portable / NetworkInterface / Zynq / x_emacpsif_physpeed.c
1 /*\r
2  * Copyright (c) 2007-2008, Advanced Micro Devices, Inc.\r
3  *               All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions\r
7  * are met:\r
8  *\r
9  *    * Redistributions of source code must retain the above copyright\r
10  *      notice, this list of conditions and the following disclaimer.\r
11  *    * Redistributions in binary form must reproduce the above copyright\r
12  *      notice, this list of conditions and the following disclaimer in\r
13  *      the documentation and/or other materials provided with the\r
14  *      distribution.\r
15  *    * Neither the name of Advanced Micro Devices, Inc. nor the names\r
16  *      of its contributors may be used to endorse or promote products\r
17  *      derived from this software without specific prior written\r
18  *      permission.\r
19  *\r
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31  */\r
32 \r
33 /*\r
34  * Some portions copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.\r
35  *\r
36  * Xilinx, Inc.\r
37  * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
38  * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
39  * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
40  * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
41  * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
42  * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
43  * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
44  * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
45  * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
46  * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
47  * AND FITNESS FOR A PARTICULAR PURPOSE.\r
48  *\r
49  */\r
50 \r
51 /* Standard includes. */\r
52 #include <stdint.h>\r
53 #include <stdio.h>\r
54 #include <stdlib.h>\r
55 \r
56 #include "Zynq/x_emacpsif.h"\r
57 //#include "lwipopts.h"\r
58 #include "xparameters_ps.h"\r
59 #include "xparameters.h"\r
60 \r
61 /* FreeRTOS includes. */\r
62 #include "FreeRTOS.h"\r
63 #include "task.h"\r
64 #include "queue.h"\r
65 #include "semphr.h"\r
66 \r
67 ///* FreeRTOS+TCP includes. */\r
68 /* FreeRTOS+TCP includes. */\r
69 #include "FreeRTOS_IP.h"\r
70 #include "FreeRTOS_Sockets.h"\r
71 #include "FreeRTOS_IP_Private.h"\r
72 #include "NetworkBufferManagement.h"\r
73 \r
74 int phy_detected = 0;\r
75 \r
76 /*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c\r
77  *** to run it on a PEEP board\r
78  ***/\r
79 \r
80 /* Advertisement control register. */\r
81 #define ADVERTISE_10HALF                0x0020  /* Try for 10mbps half-duplex  */\r
82 #define ADVERTISE_10FULL                0x0040  /* Try for 10mbps full-duplex  */\r
83 #define ADVERTISE_100HALF               0x0080  /* Try for 100mbps half-duplex */\r
84 #define ADVERTISE_100FULL               0x0100  /* Try for 100mbps full-duplex */\r
85 \r
86 #define ADVERTISE_100_AND_10    (ADVERTISE_10FULL | ADVERTISE_100FULL | \\r
87                                                                 ADVERTISE_10HALF | ADVERTISE_100HALF)\r
88 #define ADVERTISE_100                   (ADVERTISE_100FULL | ADVERTISE_100HALF)\r
89 #define ADVERTISE_10                    (ADVERTISE_10FULL | ADVERTISE_10HALF)\r
90 \r
91 #define ADVERTISE_1000                  0x0300\r
92 \r
93 \r
94 //#define PHY_REG_00_BMCR            0x00 // Basic mode control register\r
95 //#define PHY_REG_01_BMSR            0x01 // Basic mode status register\r
96 //#define PHY_REG_02_PHYSID1         0x02 // PHYS ID 1\r
97 //#define PHY_REG_03_PHYSID2         0x03 // PHYS ID 2\r
98 //#define PHY_REG_04_ADVERTISE       0x04 // Advertisement control reg\r
99 \r
100 #define IEEE_CONTROL_REG_OFFSET                         0\r
101 #define IEEE_STATUS_REG_OFFSET                          1\r
102 #define IEEE_AUTONEGO_ADVERTISE_REG                     4\r
103 #define IEEE_PARTNER_ABILITIES_1_REG_OFFSET     5\r
104 #define IEEE_1000_ADVERTISE_REG_OFFSET          9\r
105 #define IEEE_PARTNER_ABILITIES_3_REG_OFFSET     10\r
106 #define IEEE_COPPER_SPECIFIC_CONTROL_REG        16\r
107 #define IEEE_SPECIFIC_STATUS_REG                        17\r
108 #define IEEE_COPPER_SPECIFIC_STATUS_REG_2       19\r
109 #define IEEE_CONTROL_REG_MAC                            21\r
110 #define IEEE_PAGE_ADDRESS_REGISTER                      22\r
111 \r
112 \r
113 #define IEEE_CTRL_1GBPS_LINKSPEED_MASK          0x2040\r
114 #define IEEE_CTRL_LINKSPEED_MASK                        0x0040\r
115 #define IEEE_CTRL_LINKSPEED_1000M                       0x0040\r
116 #define IEEE_CTRL_LINKSPEED_100M                        0x2000\r
117 #define IEEE_CTRL_LINKSPEED_10M                         0x0000\r
118 #define IEEE_CTRL_RESET_MASK                            0x8000\r
119 #define IEEE_CTRL_AUTONEGOTIATE_ENABLE          0x1000\r
120 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
121 #define IEEE_CTRL_RESET                         0x9140\r
122 #define IEEE_CTRL_ISOLATE_DISABLE               0xFBFF\r
123 #endif\r
124 #define IEEE_STAT_AUTONEGOTIATE_CAPABLE         0x0008\r
125 #define IEEE_STAT_AUTONEGOTIATE_COMPLETE        0x0020\r
126 #define IEEE_STAT_AUTONEGOTIATE_RESTART         0x0200\r
127 #define IEEE_STAT_1GBPS_EXTENSIONS                      0x0100\r
128 #define IEEE_AN1_ABILITY_MASK                           0x1FE0\r
129 #define IEEE_AN3_ABILITY_MASK_1GBPS                     0x0C00\r
130 #define IEEE_AN1_ABILITY_MASK_100MBPS           0x0380\r
131 #define IEEE_AN1_ABILITY_MASK_10MBPS            0x0060\r
132 #define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK      0x0030\r
133 \r
134 #define IEEE_ASYMMETRIC_PAUSE_MASK                      0x0800\r
135 #define IEEE_PAUSE_MASK                                         0x0400\r
136 #define IEEE_AUTONEG_ERROR_MASK                         0x8000\r
137 \r
138 #define PHY_DETECT_REG  1\r
139 #define PHY_DETECT_MASK 0x1808\r
140 \r
141 #define XEMACPS_GMII2RGMII_SPEED1000_FD         0x140\r
142 #define XEMACPS_GMII2RGMII_SPEED100_FD          0x2100\r
143 #define XEMACPS_GMII2RGMII_SPEED10_FD           0x100\r
144 #define XEMACPS_GMII2RGMII_REG_NUM                      0x10\r
145 \r
146 /* Frequency setting */\r
147 #define SLCR_LOCK_ADDR                  (XPS_SYS_CTRL_BASEADDR + 0x4)\r
148 #define SLCR_UNLOCK_ADDR                (XPS_SYS_CTRL_BASEADDR + 0x8)\r
149 #define SLCR_GEM0_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x140)\r
150 #define SLCR_GEM1_CLK_CTRL_ADDR (XPS_SYS_CTRL_BASEADDR + 0x144)\r
151 #ifdef PEEP\r
152 #define SLCR_GEM_10M_CLK_CTRL_VALUE             0x00103031\r
153 #define SLCR_GEM_100M_CLK_CTRL_VALUE    0x00103001\r
154 #define SLCR_GEM_1G_CLK_CTRL_VALUE              0x00103011\r
155 #endif\r
156 #define SLCR_LOCK_KEY_VALUE                     0x767B\r
157 #define SLCR_UNLOCK_KEY_VALUE                   0xDF0D\r
158 #define SLCR_ADDR_GEM_RST_CTRL                  (XPS_SYS_CTRL_BASEADDR + 0x214)\r
159 #define EMACPS_SLCR_DIV_MASK                    0xFC0FC0FF\r
160 \r
161 #define EMAC0_BASE_ADDRESS                              0xE000B000\r
162 #define EMAC1_BASE_ADDRESS                              0xE000C000\r
163 \r
164 static int detect_phy(XEmacPs *xemacpsp)\r
165 {\r
166         u16 phy_reg;\r
167         u32 phy_addr;\r
168 \r
169         for (phy_addr = 31; phy_addr > 0; phy_addr--) {\r
170                 XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,\r
171                                                         &phy_reg);\r
172 \r
173                 if ((phy_reg != 0xFFFF) &&\r
174                         ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {\r
175                         /* Found a valid PHY address */\r
176                         FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected at address %d.\r\n",\r
177                                                                                                                                         phy_addr));\r
178                         FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected.\n" ) );\r
179                         phy_detected = phy_addr;\r
180                         return phy_addr;\r
181                 }\r
182         }\r
183 \r
184         FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected.  Assuming a PHY at address 0\n" ) );\r
185 \r
186         /* default to zero */\r
187         return 0;\r
188 }\r
189 \r
190 #ifdef PEEP\r
191 unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)\r
192 {\r
193 \r
194         u16 control;\r
195         u16 status;\r
196         u16 partner_capabilities;\r
197         u16 partner_capabilities_1000;\r
198         u16 phylinkspeed;\r
199         u32 phy_addr = detect_phy(xemacpsp);\r
200 \r
201         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
202                                                                                                                         ADVERTISE_1000);\r
203         /* Advertise PHY speed of 100 and 10 Mbps */\r
204         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
205                                                                                                         ADVERTISE_100_AND_10);\r
206 \r
207         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,\r
208                                                                                                                                 &control);\r
209         control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |\r
210                                         IEEE_STAT_AUTONEGOTIATE_RESTART);\r
211 \r
212         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
213 \r
214         /* Read PHY control and status registers is successful. */\r
215         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
216         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);\r
217 \r
218         if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &\r
219                                         IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {\r
220 \r
221                 while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {\r
222                         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,\r
223                                                                                                                                 &status);\r
224                 }\r
225 \r
226                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,\r
227                                                                                                                         &partner_capabilities);\r
228 \r
229                 if (status & IEEE_STAT_1GBPS_EXTENSIONS) {\r
230                         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,\r
231                                                                                                                 &partner_capabilities_1000);\r
232                         if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS)\r
233                                 return 1000;\r
234                 }\r
235 \r
236                 if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)\r
237                         return 100;\r
238                 if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)\r
239                         return 10;\r
240 \r
241                 xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n",\r
242                                 __FUNCTION__);\r
243                 return 10;\r
244 \r
245         } else {\r
246 \r
247                 /* Update TEMAC speed accordingly */\r
248                 if (status & IEEE_STAT_1GBPS_EXTENSIONS) {\r
249                         /* Get commanded link speed */\r
250                         phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;\r
251 \r
252                         switch (phylinkspeed) {\r
253                                 case (IEEE_CTRL_LINKSPEED_1000M):\r
254                                         return 1000;\r
255                                 case (IEEE_CTRL_LINKSPEED_100M):\r
256                                         return 100;\r
257                                 case (IEEE_CTRL_LINKSPEED_10M):\r
258                                         return 10;\r
259                                 default:\r
260                                         xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n",\r
261                                                         __FUNCTION__, phylinkspeed);\r
262                                         return 10;\r
263                         }\r
264 \r
265                 } else {\r
266 \r
267                         return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;\r
268 \r
269                 }\r
270         }\r
271 }\r
272 \r
273 #else /* Zynq */\r
274 unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)\r
275 {\r
276         u16 temp;\r
277         u16 control;\r
278         u16 status;\r
279         u16 partner_capabilities;\r
280 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
281         u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;\r
282 #else\r
283         u32 phy_addr = detect_phy(xemacpsp);\r
284 #endif\r
285         xil_printf("Start PHY autonegotiation \r\n");\r
286 \r
287 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
288 #else\r
289         XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);\r
290         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);\r
291         control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;\r
292         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);\r
293 \r
294         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
295 \r
296         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);\r
297         control |= IEEE_ASYMMETRIC_PAUSE_MASK;\r
298         control |= IEEE_PAUSE_MASK;\r
299         control |= ADVERTISE_100;\r
300         control |= ADVERTISE_10;\r
301         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);\r
302 \r
303         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
304                                                                                                                                         &control);\r
305         control |= ADVERTISE_1000;\r
306         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
307                                                                                                                                         control);\r
308 \r
309         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
310         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,\r
311                                                                                                                                 &control);\r
312         control |= (7 << 12);   /* max number of gigabit attempts */\r
313         control |= (1 << 11);   /* enable downshift */\r
314         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,\r
315                                                                                                                                 control);\r
316 #endif\r
317         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
318         control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;\r
319         control |= IEEE_STAT_AUTONEGOTIATE_RESTART;\r
320 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
321     control &= IEEE_CTRL_ISOLATE_DISABLE;\r
322 #endif\r
323 \r
324         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
325 \r
326 \r
327 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
328 #else\r
329         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
330         control |= IEEE_CTRL_RESET_MASK;\r
331         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
332 \r
333         while (1) {\r
334                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
335                 if (control & IEEE_CTRL_RESET_MASK)\r
336                         continue;\r
337                 else\r
338                         break;\r
339         }\r
340 #endif\r
341         xil_printf("Waiting for PHY to complete autonegotiation.\r\n");\r
342 \r
343         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);\r
344         while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {\r
345                 sleep(1);\r
346 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
347 #else\r
348                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,\r
349                                                                                                                                         &temp);\r
350                 if (temp & IEEE_AUTONEG_ERROR_MASK) {\r
351                         xil_printf("Auto negotiation error \r\n");\r
352                 }\r
353 #endif\r
354                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,\r
355                                                                                                                                 &status);\r
356                 }\r
357 \r
358         xil_printf("autonegotiation complete \r\n");\r
359 \r
360 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
361 #else\r
362         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);\r
363 #endif\r
364 \r
365 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
366         xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");\r
367         XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);\r
368         while(!(temp & 0x8000)) {\r
369                 XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);\r
370         }\r
371         if((temp & 0x0C00) == 0x0800) {\r
372                 XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
373                 return 1000;\r
374         }\r
375         else if((temp & 0x0C00) == 0x0400) {\r
376                 XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
377                 return 100;\r
378         }\r
379         else if((temp & 0x0C00) == 0x0000) {\r
380                 XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
381                 return 10;\r
382         } else {\r
383                 xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\r\n");\r
384                 XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
385                 XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);\r
386                 return 10;\r
387         }\r
388 #else\r
389         if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */\r
390                 return 1000;\r
391         else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */\r
392                 return 100;\r
393         else                                    /* 10Mbps */\r
394                 return 10;\r
395 #endif\r
396 }\r
397 #endif\r
398 \r
399 unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)\r
400 {\r
401         u16 control;\r
402         u32 phy_addr = detect_phy(xemacpsp);\r
403 \r
404         XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);\r
405         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);\r
406         control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;\r
407         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);\r
408 \r
409         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
410 \r
411         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);\r
412         control |= IEEE_ASYMMETRIC_PAUSE_MASK;\r
413         control |= IEEE_PAUSE_MASK;\r
414         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);\r
415 \r
416         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
417         control &= ~IEEE_CTRL_LINKSPEED_1000M;\r
418         control &= ~IEEE_CTRL_LINKSPEED_100M;\r
419         control &= ~IEEE_CTRL_LINKSPEED_10M;\r
420 \r
421         if (speed == 1000) {\r
422                 control |= IEEE_CTRL_LINKSPEED_1000M;\r
423         }\r
424 \r
425         else if (speed == 100) {\r
426                 control |= IEEE_CTRL_LINKSPEED_100M;\r
427                 /* Dont advertise PHY speed of 1000 Mbps */\r
428                 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);\r
429                 /* Dont advertise PHY speed of 10 Mbps */\r
430                 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
431                                                                                                                                 ADVERTISE_100);\r
432         }\r
433 \r
434         else if (speed == 10) {\r
435                 control |= IEEE_CTRL_LINKSPEED_10M;\r
436                 /* Dont advertise PHY speed of 1000 Mbps */\r
437                 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
438                                                                                                                                                         0);\r
439                 /* Dont advertise PHY speed of 100 Mbps */\r
440                 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
441                                                                                                                                 ADVERTISE_10);\r
442         }\r
443 \r
444         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,\r
445                                                                                         control | IEEE_CTRL_RESET_MASK);\r
446         {\r
447                 volatile int wait;\r
448                 for (wait=0; wait < 100000; wait++);\r
449         }\r
450         return 0;\r
451 }\r
452 \r
453 static void SetUpSLCRDivisors(int mac_baseaddr, int speed)\r
454 {\r
455         volatile u32 slcrBaseAddress;\r
456 #ifndef PEEP\r
457         u32 SlcrDiv0;\r
458         u32 SlcrDiv1=0;\r
459         u32 SlcrTxClkCntrl;\r
460 #endif\r
461 \r
462         *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;\r
463 \r
464         if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
465                 slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;\r
466         } else {\r
467                 slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;\r
468         }\r
469 #ifdef PEEP\r
470         if (speed == 1000) {\r
471                 *(volatile unsigned int *)(slcrBaseAddress) =\r
472                                                                                         SLCR_GEM_1G_CLK_CTRL_VALUE;\r
473         } else if (speed == 100) {\r
474                 *(volatile unsigned int *)(slcrBaseAddress) =\r
475                                                                                         SLCR_GEM_100M_CLK_CTRL_VALUE;\r
476         } else {\r
477                 *(volatile unsigned int *)(slcrBaseAddress) =\r
478                                                                                         SLCR_GEM_10M_CLK_CTRL_VALUE;\r
479         }\r
480 #else\r
481         if (speed == 1000) {\r
482                 if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
483 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0\r
484                         SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;\r
485                         SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;\r
486 #endif\r
487                 } else {\r
488 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0\r
489                         SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;\r
490                         SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;\r
491 #endif\r
492                 }\r
493         } else if (speed == 100) {\r
494                 if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
495 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0\r
496                         SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;\r
497                         SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;\r
498 #endif\r
499                 } else {\r
500 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0\r
501                         SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;\r
502                         SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;\r
503 #endif\r
504                 }\r
505         } else {\r
506                 if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
507 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0\r
508                         SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;\r
509                         SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;\r
510 #endif\r
511                 } else {\r
512 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0\r
513                         SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;\r
514                         SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;\r
515 #endif\r
516                 }\r
517         }\r
518         SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress);\r
519         SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;\r
520         SlcrTxClkCntrl |= (SlcrDiv1 << 20);\r
521         SlcrTxClkCntrl |= (SlcrDiv0 << 8);\r
522         *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;\r
523 #endif\r
524         *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;\r
525         return;\r
526 }\r
527 \r
528 \r
529 unsigned link_speed;\r
530 unsigned Phy_Setup (XEmacPs *xemacpsp)\r
531 {\r
532         unsigned long conv_present = 0;\r
533         unsigned long convspeeddupsetting = 0;\r
534         unsigned long convphyaddr = 0;\r
535 \r
536 #ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR\r
537         convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;\r
538         conv_present = 1;\r
539 #else\r
540 #ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR\r
541         convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;\r
542         conv_present = 1;\r
543 #endif\r
544 #endif\r
545 \r
546 #ifdef  ipconfigNIC_LINKSPEED_AUTODETECT\r
547         link_speed = get_IEEE_phy_speed(xemacpsp);\r
548         if (link_speed == 1000) {\r
549                 SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);\r
550                 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;\r
551         } else if (link_speed == 100) {\r
552                 SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);\r
553                 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;\r
554         } else {\r
555                 SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);\r
556                 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;\r
557         }\r
558 #elif   defined(ipconfigNIC_LINKSPEED1000)\r
559         SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);\r
560         link_speed = 1000;\r
561         configure_IEEE_phy_speed(xemacpsp, link_speed);\r
562         convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;\r
563         sleep(1);\r
564 #elif   defined(ipconfigNIC_LINKSPEED100)\r
565         SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);\r
566         link_speed = 100;\r
567         configure_IEEE_phy_speed(xemacpsp, link_speed);\r
568         convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;\r
569         sleep(1);\r
570 #elif   defined(ipconfigNIC_LINKSPEED10)\r
571         SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);\r
572         link_speed = 10;\r
573         configure_IEEE_phy_speed(xemacpsp, link_speed);\r
574         convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;\r
575         sleep(1);\r
576 #endif\r
577         if (conv_present) {\r
578                 XEmacPs_PhyWrite(xemacpsp, convphyaddr,\r
579                 XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);\r
580         }\r
581 \r
582         xil_printf("link speed: %d\r\n", link_speed);\r
583         return link_speed;\r
584 }\r
585 \r