]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/RX600_RX63N-RSK_Renesas/RTOSDemo/webserver/phy.c
Fix spelling issues.
[freertos] / FreeRTOS / Demo / RX600_RX63N-RSK_Renesas / 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 uint16_t  _phy_read( uint16_t reg_addr );\r
69 void  _phy_write( uint16_t reg_addr, uint16_t data );\r
70 void  _phy_preamble( void );\r
71 void  _phy_reg_set( uint16_t reg_addr, int32_t option );\r
72 void  _phy_reg_read( uint16_t *data );\r
73 void  _phy_reg_write( uint16_t 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 int16_t  phy_init( void )\r
90 {\r
91   uint16_t reg;\r
92   uint32_t 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_PERIOD_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 int16_t phy_set_autonegotiate( void )\r
149 {\r
150   uint16_t reg;\r
151   uint32_t 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_PERIOD_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       /* Get the link partner response */\r
179           reg = (int16_t)_phy_read(AN_LINK_PARTNER_ABILITY_REG);\r
180           \r
181           if (reg & ( 1 << 8 ) )\r
182           {\r
183                   return PHY_LINK_100F;\r
184           }\r
185           if (reg & ( 1 << 7 ) )\r
186           {\r
187                   return PHY_LINK_100H;\r
188           }\r
189           if (reg & ( 1 << 6 ) )\r
190           {\r
191                   return PHY_LINK_10F;\r
192           }\r
193           if (reg & 1 << 5 )\r
194           {\r
195                   return PHY_LINK_10H;\r
196           }       \r
197 \r
198           return (-1);\r
199   }\r
200 }\r
201 \r
202 \r
203 /**\r
204  * Internal functions\r
205  */\r
206 \r
207 /******************************************************************************\r
208 * Function Name: _phy_read\r
209 * Description  : Reads a PHY register\r
210 * Arguments    : reg_addr - address of the PHY register\r
211 * Return Value : read value\r
212 ******************************************************************************/\r
213 uint16_t _phy_read( uint16_t reg_addr )\r
214 {\r
215   uint16_t data;\r
216 \r
217   _phy_preamble();\r
218   _phy_reg_set( reg_addr, PHY_READ );\r
219   _phy_ta_z0();\r
220   _phy_reg_read( &data );\r
221   _phy_ta_z0();\r
222 \r
223   return( data );\r
224 }\r
225 \r
226 /******************************************************************************\r
227 * Function Name: _phy_write\r
228 * Description  : Writes to a PHY register\r
229 * Arguments    : reg_addr - address of the PHY register\r
230 *              : data - value\r
231 * Return Value : none\r
232 ******************************************************************************/\r
233 void  _phy_write( uint16_t reg_addr, uint16_t data )\r
234 {\r
235   _phy_preamble();\r
236   _phy_reg_set( reg_addr, PHY_WRITE );\r
237   _phy_ta_10();\r
238   _phy_reg_write( data );\r
239   _phy_ta_z0();\r
240 }\r
241 \r
242 /******************************************************************************\r
243 * Function Name: _phy_preamble\r
244 * Description  : As preliminary preparation for access to the PHY module register,\r
245 *                "1" is output via the MII management interface.                  \r
246 * Arguments    : none\r
247 * Return Value : none\r
248 ******************************************************************************/\r
249 void  _phy_preamble( void )\r
250 {\r
251   int16_t i;\r
252 \r
253   i = 32;\r
254   while( i > 0 )\r
255   {\r
256     _phy_mii_write_1();\r
257     i--;\r
258   }\r
259 }\r
260 \r
261 /******************************************************************************\r
262 * Function Name: _phy_reg_set\r
263 * Description  : Sets a PHY device to read or write mode\r
264 * Arguments    : reg_addr - address of the PHY register\r
265 *              : option - mode\r
266 * Return Value : none\r
267 ******************************************************************************/\r
268 void  _phy_reg_set( uint16_t reg_addr, int32_t option )\r
269 {\r
270   int32_t    i;\r
271   uint16_t data;\r
272 \r
273   data = 0;\r
274   data = (PHY_ST << 14);        /* ST code    */\r
275 \r
276   if( option == PHY_READ )\r
277   {\r
278     data |= (PHY_READ << 12);  /* OP code(RD)  */\r
279   }\r
280   else\r
281   {\r
282     data |= (PHY_WRITE << 12);  /* OP code(WT)  */\r
283   }\r
284 \r
285   data |= (PHY_ADDR << 7);    /* PHY Address  */\r
286   data |= (reg_addr << 2);    /* Reg Address  */\r
287 \r
288   i = 14;\r
289   while( i > 0 )\r
290   {\r
291     if( (data & 0x8000) == 0 )\r
292     {\r
293       _phy_mii_write_0();\r
294     }\r
295     else\r
296     {\r
297       _phy_mii_write_1();\r
298     }\r
299     data <<= 1;\r
300     i--;\r
301   }\r
302 }\r
303 \r
304 /******************************************************************************\r
305 * Function Name: _phy_reg_read\r
306 * Description  : Reads PHY register through MII interface\r
307 * Arguments    : data - pointer to store the data read\r
308 * Return Value : none\r
309 ******************************************************************************/\r
310 void  _phy_reg_read( uint16_t *data )\r
311 {\r
312   int32_t      i, j;\r
313   uint16_t   reg_data;\r
314 \r
315   reg_data = 0;\r
316   i = 16;\r
317   while( i > 0 )\r
318   {\r
319     for(j = MDC_WAIT; j > 0; j--)\r
320         {\r
321         ETHERC.PIR.LONG = 0x00000000;\r
322     }\r
323     for(j = MDC_WAIT; j > 0; j--)\r
324         {\r
325         ETHERC.PIR.LONG = 0x00000001;\r
326     }\r
327     \r
328         reg_data <<= 1;\r
329     reg_data |= (uint16_t)((ETHERC.PIR.LONG & 0x00000008) >> 3);  /* MDI read  */\r
330 \r
331     for(j = MDC_WAIT; j > 0; j--)\r
332         {\r
333         ETHERC.PIR.LONG = 0x00000001;\r
334     }\r
335     for(j = MDC_WAIT; j > 0; j--)\r
336         {\r
337         ETHERC.PIR.LONG = 0x00000000;\r
338     }\r
339     i--;\r
340   }\r
341   *data = reg_data;\r
342 }\r
343 \r
344 /******************************************************************************\r
345 * Function Name: _phy_reg_write\r
346 * Description  : Writes to PHY register through MII interface\r
347 * Arguments    : data - value to write\r
348 * Return Value : none\r
349 ******************************************************************************/\r
350 void  _phy_reg_write( uint16_t data )\r
351 {\r
352   int32_t  i;\r
353 \r
354   i = 16;\r
355   while( i > 0 )\r
356   {\r
357     if( (data & 0x8000) == 0 )\r
358     {\r
359       _phy_mii_write_0();\r
360     }\r
361     else\r
362     {\r
363       _phy_mii_write_1();\r
364     }\r
365     i--;\r
366     data <<= 1;\r
367   }\r
368 }\r
369 \r
370 /******************************************************************************\r
371 * Function Name: _phy_ta_z0\r
372 * Description  : Performs bus release so that PHY can drive data\r
373 *              : for read operation \r
374 * Arguments    : none\r
375 * Return Value : none\r
376 ******************************************************************************/\r
377 void  _phy_ta_z0( void )\r
378 {\r
379     int32_t j;\r
380 \r
381     for(j = MDC_WAIT; j > 0; j--)\r
382         {\r
383         ETHERC.PIR.LONG = 0x00000000;\r
384     }\r
385     for(j = MDC_WAIT; j > 0; j--)\r
386         {\r
387         ETHERC.PIR.LONG = 0x00000001;\r
388     }\r
389     for(j = MDC_WAIT; j > 0; j--)\r
390         {\r
391         ETHERC.PIR.LONG = 0x00000001;\r
392     }\r
393     for(j = MDC_WAIT; j > 0; j--)\r
394         {\r
395         ETHERC.PIR.LONG = 0x00000000;\r
396     }\r
397 }\r
398 \r
399 /******************************************************************************\r
400 * Function Name: _phy_ta_10\r
401 * Description  : Switches data bus so MII interface can drive data\r
402 *              : for write operation \r
403 * Arguments    : none\r
404 * Return Value : none\r
405 ******************************************************************************/\r
406 void _phy_ta_10(void)\r
407 {\r
408     _phy_mii_write_1();\r
409     _phy_mii_write_0();\r
410 }\r
411 \r
412 /******************************************************************************\r
413 * Function Name: _phy_mii_write_1\r
414 * Description  : Outputs 1 to the MII interface \r
415 * Arguments    : none\r
416 * Return Value : none\r
417 ******************************************************************************/\r
418 void  _phy_mii_write_1( void )\r
419 {\r
420     int32_t j;\r
421 \r
422     for(j = MDC_WAIT; j > 0; j--)\r
423         {\r
424         ETHERC.PIR.LONG = 0x00000006;\r
425     }\r
426     for(j = MDC_WAIT; j > 0; j--)\r
427         {\r
428         ETHERC.PIR.LONG = 0x00000007;\r
429     }\r
430     for(j = MDC_WAIT; j > 0; j--)\r
431         {\r
432         ETHERC.PIR.LONG = 0x00000007;\r
433     }\r
434     for(j = MDC_WAIT; j > 0; j--)\r
435         {\r
436         ETHERC.PIR.LONG = 0x00000006;\r
437     }\r
438 }\r
439 \r
440 /******************************************************************************\r
441 * Function Name: _phy_mii_write_0\r
442 * Description  : Outputs 0 to the MII interface \r
443 * Arguments    : none\r
444 * Return Value : none\r
445 ******************************************************************************/\r
446 void  _phy_mii_write_0( void )\r
447 {\r
448     int32_t j;\r
449 \r
450     for(j = MDC_WAIT; j > 0; j--)\r
451         {\r
452         ETHERC.PIR.LONG = 0x00000002;\r
453     }\r
454     for(j = MDC_WAIT; j > 0; j--)\r
455         {\r
456         ETHERC.PIR.LONG = 0x00000003;\r
457     }\r
458     for(j = MDC_WAIT; j > 0; j--)\r
459         {\r
460         ETHERC.PIR.LONG = 0x00000003;\r
461     }\r
462     for(j = MDC_WAIT; j > 0; j--)\r
463         {\r
464         ETHERC.PIR.LONG = 0x00000002;\r
465     }\r
466 }\r
467 \r
468 \r