]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c
d1999a73e8041c2dca776272d5333b21b17f7042
[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 static int detect_phy(XEmacPs *xemacpsp)\r
163 {\r
164         u16 id_lower, id_upper;\r
165         u32 phy_addr, id;\r
166 \r
167         for (phy_addr = 0; phy_addr < 32; phy_addr++) {\r
168                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PHYSID1_OFFSET, &id_lower);\r
169 \r
170                 if ((id_lower != ( u16 )0xFFFFu) && (id_lower != ( u16 )0x0u)) {\r
171 \r
172                         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PHYSID2_OFFSET, &id_upper);\r
173                         id = ( ( ( uint32_t ) id_upper ) << 16 ) | ( id_lower & 0xFFF0 );\r
174                         FreeRTOS_printf( ("XEmacPs detect_phy: %04lX at address %d.\n", id, phy_addr ) );\r
175                         phy_detected = phy_addr;\r
176                         return phy_addr;\r
177                 }\r
178         }\r
179 \r
180         FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected.  Assuming a PHY at address 0\n" ) );\r
181 \r
182         /* default to zero */\r
183         return 0;\r
184 }\r
185 \r
186 #ifdef PEEP\r
187 unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)\r
188 {\r
189 \r
190         u16 control;\r
191         u16 status;\r
192         u16 partner_capabilities;\r
193         u16 partner_capabilities_1000;\r
194         u16 phylinkspeed;\r
195         u32 phy_addr = detect_phy(xemacpsp);\r
196 \r
197         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
198                                                                                                                         ADVERTISE_1000);\r
199         /* Advertise PHY speed of 100 and 10 Mbps */\r
200         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
201                                                                                                         ADVERTISE_100_AND_10);\r
202 \r
203         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,\r
204                                                                                                                                 &control);\r
205         control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |\r
206                                         IEEE_STAT_AUTONEGOTIATE_RESTART);\r
207 \r
208         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
209 \r
210         /* Read PHY control and status registers is successful. */\r
211         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
212         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);\r
213 \r
214         if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &\r
215                                         IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {\r
216 \r
217                 while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {\r
218                         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,\r
219                                                                                                                                 &status);\r
220                 }\r
221 \r
222                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,\r
223                                                                                                                         &partner_capabilities);\r
224 \r
225                 if (status & IEEE_STAT_1GBPS_EXTENSIONS) {\r
226                         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,\r
227                                                                                                                 &partner_capabilities_1000);\r
228                         if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS)\r
229                                 return 1000;\r
230                 }\r
231 \r
232                 if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)\r
233                         return 100;\r
234                 if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)\r
235                         return 10;\r
236 \r
237                 FreeRTOS_printf( ( "%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\n",\r
238                                 __FUNCTION__ ) );\r
239                 return 10;\r
240 \r
241         } else {\r
242 \r
243                 /* Update TEMAC speed accordingly */\r
244                 if (status & IEEE_STAT_1GBPS_EXTENSIONS) {\r
245                         /* Get commanded link speed */\r
246                         phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;\r
247 \r
248                         switch (phylinkspeed) {\r
249                                 case (IEEE_CTRL_LINKSPEED_1000M):\r
250                                         return 1000;\r
251                                 case (IEEE_CTRL_LINKSPEED_100M):\r
252                                         return 100;\r
253                                 case (IEEE_CTRL_LINKSPEED_10M):\r
254                                         return 10;\r
255                                 default:\r
256                                         FreeRTOS_printf( ( "%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\n",\r
257                                                         __FUNCTION__, phylinkspeed ) );\r
258                                         return 10;\r
259                         }\r
260 \r
261                 } else {\r
262 \r
263                         return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;\r
264 \r
265                 }\r
266         }\r
267 }\r
268 \r
269 #else /* Zynq */\r
270 unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)\r
271 {\r
272         u16 temp;\r
273         u16 control;\r
274         u16 status;\r
275         u16 partner_capabilities;\r
276 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
277         u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;\r
278 #else\r
279         u32 phy_addr = detect_phy(xemacpsp);\r
280 #endif\r
281         FreeRTOS_printf( ( "Start PHY autonegotiation \n" ) );\r
282 \r
283 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
284 #else\r
285         XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);\r
286         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);\r
287         control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;\r
288         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);\r
289 \r
290         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
291 \r
292         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);\r
293         control |= IEEE_ASYMMETRIC_PAUSE_MASK;\r
294         control |= IEEE_PAUSE_MASK;\r
295         control |= ADVERTISE_100;\r
296         control |= ADVERTISE_10;\r
297         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);\r
298 \r
299         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
300                                                                                                                                         &control);\r
301         control |= ADVERTISE_1000;\r
302         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
303                                                                                                                                         control);\r
304 \r
305         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
306         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,\r
307                                                                                                                                 &control);\r
308         control |= (7 << 12);   /* max number of gigabit attempts */\r
309         control |= (1 << 11);   /* enable downshift */\r
310         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,\r
311                                                                                                                                 control);\r
312 #endif\r
313         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
314         control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;\r
315         control |= IEEE_STAT_AUTONEGOTIATE_RESTART;\r
316 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
317     control &= IEEE_CTRL_ISOLATE_DISABLE;\r
318 #endif\r
319 \r
320         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
321 \r
322 \r
323 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
324 #else\r
325         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
326         control |= IEEE_CTRL_RESET_MASK;\r
327         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
328 \r
329         while (1) {\r
330                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
331                 if (control & IEEE_CTRL_RESET_MASK)\r
332                         continue;\r
333                 else\r
334                         break;\r
335         }\r
336 #endif\r
337         FreeRTOS_printf( ( "Waiting for PHY to complete autonegotiation.\n" ) );\r
338 \r
339         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);\r
340         while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {\r
341                 vTaskDelay(1);\r
342 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
343 #else\r
344                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,\r
345                                                                                                                                         &temp);\r
346                 if (temp & IEEE_AUTONEG_ERROR_MASK) {\r
347                         FreeRTOS_printf( ( "Auto negotiation error \n" ) );\r
348                 }\r
349 #endif\r
350                 XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,\r
351                                                                                                                                 &status);\r
352                 }\r
353 \r
354         FreeRTOS_printf( ( "autonegotiation complete \n" ) );\r
355 \r
356 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
357 #else\r
358         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);\r
359 #endif\r
360 \r
361 #if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
362         FreeRTOS_printf( ( "Waiting for Link to be up; Polling for SGMII core Reg \n" ) );\r
363         XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);\r
364         while(!(temp & 0x8000)) {\r
365                 XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);\r
366         }\r
367         if((temp & 0x0C00) == 0x0800) {\r
368                 XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
369                 return 1000;\r
370         }\r
371         else if((temp & 0x0C00) == 0x0400) {\r
372                 XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
373                 return 100;\r
374         }\r
375         else if((temp & 0x0C00) == 0x0000) {\r
376                 XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
377                 return 10;\r
378         } else {\r
379                 FreeRTOS_printf( ( "get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\n" ) );\r
380                 XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
381                 XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);\r
382                 return 10;\r
383         }\r
384 #else\r
385         if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */\r
386                 return 1000;\r
387         else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */\r
388                 return 100;\r
389         else                                    /* 10Mbps */\r
390                 return 10;\r
391 #endif\r
392 }\r
393 #endif\r
394 \r
395 unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)\r
396 {\r
397         u16 control;\r
398         u32 phy_addr = detect_phy(xemacpsp);\r
399 \r
400         XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);\r
401         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);\r
402         control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;\r
403         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);\r
404 \r
405         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
406 \r
407         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);\r
408         control |= IEEE_ASYMMETRIC_PAUSE_MASK;\r
409         control |= IEEE_PAUSE_MASK;\r
410         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);\r
411 \r
412         XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
413         control &= ~IEEE_CTRL_LINKSPEED_1000M;\r
414         control &= ~IEEE_CTRL_LINKSPEED_100M;\r
415         control &= ~IEEE_CTRL_LINKSPEED_10M;\r
416 \r
417         if (speed == 1000) {\r
418                 control |= IEEE_CTRL_LINKSPEED_1000M;\r
419         }\r
420 \r
421         else if (speed == 100) {\r
422                 control |= IEEE_CTRL_LINKSPEED_100M;\r
423                 /* Dont advertise PHY speed of 1000 Mbps */\r
424                 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);\r
425                 /* Dont advertise PHY speed of 10 Mbps */\r
426                 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
427                                                                                                                                 ADVERTISE_100);\r
428         }\r
429 \r
430         else if (speed == 10) {\r
431                 control |= IEEE_CTRL_LINKSPEED_10M;\r
432                 /* Dont advertise PHY speed of 1000 Mbps */\r
433                 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
434                                                                                                                                                         0);\r
435                 /* Dont advertise PHY speed of 100 Mbps */\r
436                 XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
437                                                                                                                                 ADVERTISE_10);\r
438         }\r
439 \r
440         XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,\r
441                                                                                         control | IEEE_CTRL_RESET_MASK);\r
442         {\r
443                 volatile int wait;\r
444                 for (wait=0; wait < 100000; wait++);\r
445         }\r
446         return 0;\r
447 }\r
448 \r
449 static void SetUpSLCRDivisors(int mac_baseaddr, int speed)\r
450 {\r
451         volatile u32 slcrBaseAddress;\r
452 #ifndef PEEP\r
453         u32 SlcrDiv0;\r
454         u32 SlcrDiv1=0;\r
455         u32 SlcrTxClkCntrl;\r
456 #endif\r
457 \r
458         *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;\r
459 \r
460         if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
461                 slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;\r
462         } else {\r
463                 slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;\r
464         }\r
465 #ifdef PEEP\r
466         if (speed == 1000) {\r
467                 *(volatile unsigned int *)(slcrBaseAddress) =\r
468                                                                                         SLCR_GEM_1G_CLK_CTRL_VALUE;\r
469         } else if (speed == 100) {\r
470                 *(volatile unsigned int *)(slcrBaseAddress) =\r
471                                                                                         SLCR_GEM_100M_CLK_CTRL_VALUE;\r
472         } else {\r
473                 *(volatile unsigned int *)(slcrBaseAddress) =\r
474                                                                                         SLCR_GEM_10M_CLK_CTRL_VALUE;\r
475         }\r
476 #else\r
477         if (speed == 1000) {\r
478                 if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
479 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0\r
480                         SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;\r
481                         SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;\r
482 #endif\r
483                 } else {\r
484 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0\r
485                         SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;\r
486                         SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;\r
487 #endif\r
488                 }\r
489         } else if (speed == 100) {\r
490                 if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
491 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0\r
492                         SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;\r
493                         SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;\r
494 #endif\r
495                 } else {\r
496 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0\r
497                         SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;\r
498                         SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;\r
499 #endif\r
500                 }\r
501         } else {\r
502                 if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
503 #ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0\r
504                         SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;\r
505                         SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;\r
506 #endif\r
507                 } else {\r
508 #ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0\r
509                         SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;\r
510                         SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;\r
511 #endif\r
512                 }\r
513         }\r
514         SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress);\r
515         SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;\r
516         SlcrTxClkCntrl |= (SlcrDiv1 << 20);\r
517         SlcrTxClkCntrl |= (SlcrDiv0 << 8);\r
518         *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;\r
519 #endif\r
520         *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;\r
521         return;\r
522 }\r
523 \r
524 \r
525 unsigned link_speed;\r
526 unsigned Phy_Setup (XEmacPs *xemacpsp)\r
527 {\r
528         unsigned long conv_present = 0;\r
529         unsigned long convspeeddupsetting = 0;\r
530         unsigned long convphyaddr = 0;\r
531 \r
532 #ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR\r
533         convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;\r
534         conv_present = 1;\r
535 #else\r
536 #ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR\r
537         convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;\r
538         conv_present = 1;\r
539 #endif\r
540 #endif\r
541 \r
542 #ifdef  ipconfigNIC_LINKSPEED_AUTODETECT\r
543         link_speed = get_IEEE_phy_speed(xemacpsp);\r
544         if (link_speed == 1000) {\r
545                 SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);\r
546                 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;\r
547         } else if (link_speed == 100) {\r
548                 SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);\r
549                 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;\r
550         } else {\r
551                 SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);\r
552                 convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;\r
553         }\r
554 #elif   defined(ipconfigNIC_LINKSPEED1000)\r
555         SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);\r
556         link_speed = 1000;\r
557         configure_IEEE_phy_speed(xemacpsp, link_speed);\r
558         convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;\r
559         vTaskDelay(1);\r
560 #elif   defined(ipconfigNIC_LINKSPEED100)\r
561         SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);\r
562         link_speed = 100;\r
563         configure_IEEE_phy_speed(xemacpsp, link_speed);\r
564         convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;\r
565         vTaskDelay(1);\r
566 #elif   defined(ipconfigNIC_LINKSPEED10)\r
567         SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);\r
568         link_speed = 10;\r
569         configure_IEEE_phy_speed(xemacpsp, link_speed);\r
570         convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;\r
571         vTaskDelay(1);\r
572 #endif\r
573         if (conv_present) {\r
574                 XEmacPs_PhyWrite(xemacpsp, convphyaddr,\r
575                 XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);\r
576         }\r
577 \r
578         FreeRTOS_printf( ( "link speed: %d\n", link_speed ) );\r
579         return link_speed;\r
580 }\r
581 \r