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