]> git.sur5r.net Git - freertos/blob - Demo/RX600_RX62N-RDK_GNURX/RTOSDemo/webserver/phy.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / RX600_RX62N-RDK_GNURX / RTOSDemo / webserver / phy.c
1 /******************************************************************************\r
2 * DISCLAIMER\r
3 \r
4 * This software is supplied by Renesas Technology Corp. and is only\r
5 * intended for use with Renesas products. No other uses are authorized.\r
6 \r
7 * This software is owned by Renesas Technology Corp. and is protected under\r
8 * all applicable laws, including copyright laws.\r
9 \r
10 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES\r
11 * REGARDING THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY,\r
12 * INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\r
13 * PARTICULAR PURPOSE AND NON-INFRINGEMENT.  ALL SUCH WARRANTIES ARE EXPRESSLY\r
14 * DISCLAIMED.\r
15 \r
16 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS\r
17 * TECHNOLOGY CORP. NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE\r
18 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES\r
19 * FOR ANY REASON RELATED TO THE THIS SOFTWARE, EVEN IF RENESAS OR ITS\r
20 * AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\r
21 \r
22 * Renesas reserves the right, without notice, to make changes to this\r
23 * software and to discontinue the availability of this software.\r
24 * By using this software, you agree to the additional terms and\r
25 * conditions found by accessing the following link:\r
26 * http://www.renesas.com/disclaimer\r
27 ******************************************************************************\r
28 * Copyright (C) 2008. Renesas Technology Corp., All Rights Reserved.\r
29 ******************************************************************************* \r
30 * File Name    : phy.c\r
31 * Version      : 1.01\r
32 * Description  : Ethernet PHY device driver\r
33 ******************************************************************************\r
34 * History : DD.MM.YYYY Version Description\r
35 *         : 15.02.2010 1.00    First Release\r
36 *         : 06.04.2010 1.01    RX62N changes\r
37 ******************************************************************************/\r
38 \r
39 \r
40 /******************************************************************************\r
41 Includes   <System Includes> , "Project Includes"\r
42 ******************************************************************************/\r
43 #include <iodefine.h>\r
44 #include "r_ether.h"\r
45 #include "phy.h"\r
46 \r
47 #include "FreeRTOS.h"\r
48 #include "task.h"\r
49 /******************************************************************************\r
50 Typedef definitions\r
51 ******************************************************************************/\r
52 \r
53 /******************************************************************************\r
54 Macro definitions\r
55 ******************************************************************************/\r
56 \r
57 /******************************************************************************\r
58 Imported global variables and functions (from other files)\r
59 ******************************************************************************/\r
60 \r
61 /******************************************************************************\r
62 Exported global variables and functions (to be accessed by other files)\r
63 ******************************************************************************/\r
64 \r
65 /******************************************************************************\r
66 Private global variables and functions\r
67 ******************************************************************************/\r
68 unsigned short  _phy_read( unsigned short reg_addr );\r
69 void  _phy_write( unsigned short reg_addr, unsigned short data );\r
70 void  _phy_preamble( void );\r
71 void  _phy_reg_set( unsigned short reg_addr, long option );\r
72 void  _phy_reg_read( unsigned short *data );\r
73 void  _phy_reg_write( unsigned short data );\r
74 void  _phy_ta_z0( void );\r
75 void  _phy_ta_10( void );\r
76 void  _phy_mii_write_1( void );\r
77 void  _phy_mii_write_0( void );\r
78 \r
79 /**\r
80  * External functions\r
81  */\r
82 \r
83 /******************************************************************************\r
84 * Function Name: phy_init\r
85 * Description  : Resets Ethernet PHY device\r
86 * Arguments    : none\r
87 * Return Value : none\r
88 ******************************************************************************/\r
89 short  phy_init( void )\r
90 {\r
91   unsigned short reg;\r
92   unsigned long count;\r
93 \r
94   /* Reset PHY */\r
95   _phy_write(BASIC_MODE_CONTROL_REG, 0x8000);\r
96 \r
97   count = 0;\r
98 \r
99   do\r
100   {\r
101           vTaskDelay( 2 / portTICK_RATE_MS );\r
102       reg = _phy_read(BASIC_MODE_CONTROL_REG);\r
103           count++;\r
104   } while (reg & 0x8000 && count < PHY_RESET_WAIT);\r
105 \r
106   if( count < PHY_RESET_WAIT )\r
107   {     \r
108         return R_PHY_OK;\r
109   }\r
110 \r
111   return R_PHY_ERROR;\r
112 }\r
113 \r
114 /******************************************************************************\r
115 * Function Name: phy_set_100full\r
116 * Description  : Set Ethernet PHY device to 100 Mbps full duplex\r
117 * Arguments    : none\r
118 * Return Value : none\r
119 ******************************************************************************/\r
120 void phy_set_100full( void )\r
121 {\r
122         _phy_write(BASIC_MODE_CONTROL_REG, 0x2100);\r
123 }\r
124 \r
125 /******************************************************************************\r
126 * Function Name: phy_set_10half\r
127 * Description  : Sets Ethernet PHY device to 10 Mbps half duplexR\r
128 * Arguments    : none\r
129 * Return Value : none\r
130 ******************************************************************************/\r
131 void phy_set_10half( void )\r
132 {\r
133         _phy_write(BASIC_MODE_CONTROL_REG, 0x0000);\r
134 }\r
135 \r
136 /******************************************************************************\r
137 * Function Name: phy_set_autonegotiate\r
138 * Description  : Starts autonegotiate and reports the other side's\r
139 *              : physical capability\r
140 * Arguments    : none\r
141 * Return Value : bit 8 - Full duplex 100 mbps\r
142 *              : bit 7 - Half duplex 100 mbps\r
143 *              : bit 6 - Full duplex 10 mbps\r
144 *              : bit 5 - Half duplex 10 mbps\r
145 *              : bit 4:0 - Always set to 00001 (IEEE 802.3)\r
146 *              : -1 if error\r
147 ******************************************************************************/\r
148 short phy_set_autonegotiate( void )\r
149 {\r
150   unsigned short reg;\r
151   unsigned long count;\r
152 \r
153   _phy_write(AN_ADVERTISEMENT_REG, 0x01E1);\r
154   _phy_write(BASIC_MODE_CONTROL_REG, 0x1200);\r
155 \r
156   count = 0;\r
157 \r
158   do\r
159   {\r
160       reg = _phy_read(BASIC_MODE_STATUS_REG);\r
161       count++;\r
162           vTaskDelay( 100 / portTICK_RATE_MS );\r
163         \r
164           /* Make sure we don't break out if reg just contains 0xffff. */\r
165           if( reg == 0xffff )\r
166           {\r
167                 reg = 0;\r
168           }\r
169         \r
170   } while (!(reg & 0x0020) && (count < PHY_AUTO_NEGOTIATON_WAIT));\r
171 \r
172   if (count >= PHY_AUTO_NEGOTIATON_WAIT)\r
173   {\r
174       return R_PHY_ERROR;\r
175   }\r
176   else\r
177   {\r
178           /* National DP83640 fix */\r
179           _phy_write(0x13, 0x0006);\r
180           reg = _phy_read(0x14);\r
181           _phy_write(0x14, (reg&0x7FFF));\r
182       _phy_write(0x13, 0x0000);\r
183         \r
184       /* Get the link partner response */\r
185           reg = (short)_phy_read(AN_LINK_PARTNER_ABILITY_REG);\r
186         \r
187           if (reg & ( 1 << 8 ) )\r
188           {\r
189                   return PHY_LINK_100F;\r
190           }\r
191           if (reg & ( 1 << 7 ) )\r
192           {\r
193                   return PHY_LINK_100H;\r
194           }\r
195           if (reg & ( 1 << 6 ) )\r
196           {\r
197                   return PHY_LINK_10F;\r
198           }\r
199           if (reg & 1 << 5 )\r
200           {\r
201                   return PHY_LINK_10H;\r
202           }     \r
203 \r
204           return (-1);\r
205   }\r
206 }\r
207 \r
208 \r
209 /**\r
210  * Internal functions\r
211  */\r
212 \r
213 /******************************************************************************\r
214 * Function Name: _phy_read\r
215 * Description  : Reads a PHY register\r
216 * Arguments    : reg_addr - address of the PHY register\r
217 * Return Value : read value\r
218 ******************************************************************************/\r
219 unsigned short _phy_read( unsigned short reg_addr )\r
220 {\r
221   unsigned short data;\r
222 \r
223   _phy_preamble();\r
224   _phy_reg_set( reg_addr, PHY_READ );\r
225   _phy_ta_z0();\r
226   _phy_reg_read( &data );\r
227   _phy_ta_z0();\r
228 \r
229   return( data );\r
230 }\r
231 \r
232 /******************************************************************************\r
233 * Function Name: _phy_write\r
234 * Description  : Writes to a PHY register\r
235 * Arguments    : reg_addr - address of the PHY register\r
236 *              : data - value\r
237 * Return Value : none\r
238 ******************************************************************************/\r
239 void  _phy_write( unsigned short reg_addr, unsigned short data )\r
240 {\r
241   _phy_preamble();\r
242   _phy_reg_set( reg_addr, PHY_WRITE );\r
243   _phy_ta_10();\r
244   _phy_reg_write( data );\r
245   _phy_ta_z0();\r
246 }\r
247 \r
248 /******************************************************************************\r
249 * Function Name: _phy_preamble\r
250 * Description  : As preliminary preparation for access to the PHY module register,\r
251 *                "1" is output via the MII management interface.\r
252 * Arguments    : none\r
253 * Return Value : none\r
254 ******************************************************************************/\r
255 void  _phy_preamble( void )\r
256 {\r
257   short i;\r
258 \r
259   i = 32;\r
260   while( i > 0 )\r
261   {\r
262     _phy_mii_write_1();\r
263     i--;\r
264   }\r
265 }\r
266 \r
267 /******************************************************************************\r
268 * Function Name: _phy_reg_set\r
269 * Description  : Sets a PHY device to read or write mode\r
270 * Arguments    : reg_addr - address of the PHY register\r
271 *              : option - mode\r
272 * Return Value : none\r
273 ******************************************************************************/\r
274 void  _phy_reg_set( unsigned short reg_addr, long option )\r
275 {\r
276   long    i;\r
277   unsigned short data;\r
278 \r
279   data = 0;\r
280   data = (PHY_ST << 14);        /* ST code    */\r
281 \r
282   if( option == PHY_READ )\r
283   {\r
284     data |= (PHY_READ << 12);  /* OP code(RD)  */\r
285   }\r
286   else\r
287   {\r
288     data |= (PHY_WRITE << 12);  /* OP code(WT)  */\r
289   }\r
290 \r
291   data |= (PHY_ADDR << 7);    /* PHY Address  */\r
292   data |= (reg_addr << 2);    /* Reg Address  */\r
293 \r
294   i = 14;\r
295   while( i > 0 )\r
296   {\r
297     if( (data & 0x8000) == 0 )\r
298     {\r
299       _phy_mii_write_0();\r
300     }\r
301     else\r
302     {\r
303       _phy_mii_write_1();\r
304     }\r
305     data <<= 1;\r
306     i--;\r
307   }\r
308 }\r
309 \r
310 /******************************************************************************\r
311 * Function Name: _phy_reg_read\r
312 * Description  : Reads PHY register through MII interface\r
313 * Arguments    : data - pointer to store the data read\r
314 * Return Value : none\r
315 ******************************************************************************/\r
316 void  _phy_reg_read( unsigned short *data )\r
317 {\r
318   long      i, j;\r
319   unsigned short   reg_data;\r
320 \r
321   reg_data = 0;\r
322   i = 16;\r
323   while( i > 0 )\r
324   {\r
325     for(j = MDC_WAIT; j > 0; j--)\r
326         {\r
327         ETHERC.PIR.LONG = 0x00000000;\r
328     }\r
329     for(j = MDC_WAIT; j > 0; j--)\r
330         {\r
331         ETHERC.PIR.LONG = 0x00000001;\r
332     }\r
333 \r
334         reg_data <<= 1;\r
335     reg_data |= (unsigned short)((ETHERC.PIR.LONG & 0x00000008) >> 3);  /* MDI read  */\r
336 \r
337     for(j = MDC_WAIT; j > 0; j--)\r
338         {\r
339         ETHERC.PIR.LONG = 0x00000001;\r
340     }\r
341     for(j = MDC_WAIT; j > 0; j--)\r
342         {\r
343         ETHERC.PIR.LONG = 0x00000000;\r
344     }\r
345     i--;\r
346   }\r
347   *data = reg_data;\r
348 }\r
349 \r
350 /******************************************************************************\r
351 * Function Name: _phy_reg_write\r
352 * Description  : Writes to PHY register through MII interface\r
353 * Arguments    : data - value to write\r
354 * Return Value : none\r
355 ******************************************************************************/\r
356 void  _phy_reg_write( unsigned short data )\r
357 {\r
358   long  i;\r
359 \r
360   i = 16;\r
361   while( i > 0 )\r
362   {\r
363     if( (data & 0x8000) == 0 )\r
364     {\r
365       _phy_mii_write_0();\r
366     }\r
367     else\r
368     {\r
369       _phy_mii_write_1();\r
370     }\r
371     i--;\r
372     data <<= 1;\r
373   }\r
374 }\r
375 \r
376 /******************************************************************************\r
377 * Function Name: _phy_ta_z0\r
378 * Description  : Performs bus release so that PHY can drive data\r
379 *              : for read operation\r
380 * Arguments    : none\r
381 * Return Value : none\r
382 ******************************************************************************/\r
383 void  _phy_ta_z0( void )\r
384 {\r
385     long j;\r
386 \r
387     for(j = MDC_WAIT; j > 0; j--)\r
388         {\r
389         ETHERC.PIR.LONG = 0x00000000;\r
390     }\r
391     for(j = MDC_WAIT; j > 0; j--)\r
392         {\r
393         ETHERC.PIR.LONG = 0x00000001;\r
394     }\r
395     for(j = MDC_WAIT; j > 0; j--)\r
396         {\r
397         ETHERC.PIR.LONG = 0x00000001;\r
398     }\r
399     for(j = MDC_WAIT; j > 0; j--)\r
400         {\r
401         ETHERC.PIR.LONG = 0x00000000;\r
402     }\r
403 }\r
404 \r
405 /******************************************************************************\r
406 * Function Name: _phy_ta_10\r
407 * Description  : Switches data bus so MII interface can drive data\r
408 *              : for write operation\r
409 * Arguments    : none\r
410 * Return Value : none\r
411 ******************************************************************************/\r
412 void _phy_ta_10(void)\r
413 {\r
414     _phy_mii_write_1();\r
415     _phy_mii_write_0();\r
416 }\r
417 \r
418 /******************************************************************************\r
419 * Function Name: _phy_mii_write_1\r
420 * Description  : Outputs 1 to the MII interface\r
421 * Arguments    : none\r
422 * Return Value : none\r
423 ******************************************************************************/\r
424 void  _phy_mii_write_1( void )\r
425 {\r
426     long j;\r
427 \r
428     for(j = MDC_WAIT; j > 0; j--)\r
429         {\r
430         ETHERC.PIR.LONG = 0x00000006;\r
431     }\r
432     for(j = MDC_WAIT; j > 0; j--)\r
433         {\r
434         ETHERC.PIR.LONG = 0x00000007;\r
435     }\r
436     for(j = MDC_WAIT; j > 0; j--)\r
437         {\r
438         ETHERC.PIR.LONG = 0x00000007;\r
439     }\r
440     for(j = MDC_WAIT; j > 0; j--)\r
441         {\r
442         ETHERC.PIR.LONG = 0x00000006;\r
443     }\r
444 }\r
445 \r
446 /******************************************************************************\r
447 * Function Name: _phy_mii_write_0\r
448 * Description  : Outputs 0 to the MII interface\r
449 * Arguments    : none\r
450 * Return Value : none\r
451 ******************************************************************************/\r
452 void  _phy_mii_write_0( void )\r
453 {\r
454     long j;\r
455 \r
456     for(j = MDC_WAIT; j > 0; j--)\r
457         {\r
458         ETHERC.PIR.LONG = 0x00000002;\r
459     }\r
460     for(j = MDC_WAIT; j > 0; j--)\r
461         {\r
462         ETHERC.PIR.LONG = 0x00000003;\r
463     }\r
464     for(j = MDC_WAIT; j > 0; j--)\r
465         {\r
466         ETHERC.PIR.LONG = 0x00000003;\r
467     }\r
468     for(j = MDC_WAIT; j > 0; j--)\r
469         {\r
470         ETHERC.PIR.LONG = 0x00000002;\r
471     }\r
472 }\r
473 \r
474 \r