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