]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/eth/powerpc/quicc2/v2_0/src/EnetPHY.c
Initial revision
[karo-tx-redboot.git] / packages / devs / eth / powerpc / quicc2 / v2_0 / src / EnetPHY.c
1 //####ECOSGPLCOPYRIGHTBEGIN####
2 // -------------------------------------------
3 // This file is part of eCos, the Embedded Configurable Operating System.
4 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
5 // Copyright (C) 2002 Gary Thomas
6 //
7 // eCos is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 2 or (at your option) any later version.
10 //
11 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 // for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with eCos; if not, write to the Free Software Foundation, Inc.,
18 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 //
20 // As a special exception, if other files instantiate templates or use macros
21 // or inline functions from this file, or you compile this file and link it
22 // with other works to produce a work based on this file, this file does not
23 // by itself cause the resulting work to be covered by the GNU General Public
24 // License. However the source code for this file must still be made available
25 // in accordance with section (3) of the GNU General Public License.
26 //
27 // This exception does not invalidate any other reasons why a work based on
28 // this file might be covered by the GNU General Public License.
29 //
30 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
31 // at http://sources.redhat.com/ecos/ecos-license/
32 // -------------------------------------------
33 //####ECOSGPLCOPYRIGHTEND####
34 /*-------------------------------------------------------------------    
35 *
36 * FILE: enetPHY.c
37 *
38 * DESCRIPTION:   GPIO Management Pins driver for the LXT970a 
39 *                
40 *
41 * Modified for the mpc8260 VADS board
42 *--------------------------------------------------------------------*/
43 #include "types.h"
44 #include <cyg/hal/hal_intr.h> /* HAL_DELAY_US */
45 #include "EnetPHY.h"
46
47 /* Internal functions */
48 void    MdioSend(UINT32, UINT16);
49 UINT16  MdioReceive(UINT16);
50 UINT16  MdioFrame(MDIORW, UINT16, UINT16, UINT32);
51
52 VUINT32 * pPortDir;
53 VUINT32 * pPortData;
54
55 /*-------------------------------------------------------------------
56 *
57 * FUNCTION NAME: 
58 *
59 * DESCRIPTION:
60 *
61 * EXTERNAL EFFECT: Turns on the LXT970 transciever
62 *
63 * PARAMETERS:
64 *
65 * RETURNS: None
66 *
67 * ASSUMPTIONS:
68 *
69 *-------------------------------------------------------------------*/
70 void 
71 EnableResetPHY(volatile t_BCSR *pBCSR)
72 {
73 #ifdef CYGPKG_HAL_POWERPC_TS6
74 #define ETH_RST_MASK 0x20
75   /* The FPGA control register on the TS6 board uses the same memory
76    * location as the BCSR register on the VADS board.
77    */
78   volatile cyg_uint32 *fpga_ctrl = (cyg_uint32 *) pBCSR;
79   volatile cyg_uint32 *fpga_vers;
80   cyg_uint32 value;
81   fpga_vers = fpga_ctrl + 1;
82   value = *fpga_vers;
83   if(value >= 6){ /* version 06 of the FPGA added PHY reset control */
84     value = *fpga_ctrl;
85     /* Set the PHY reset bit */
86     value |= ETH_RST_MASK;
87     *fpga_vers = value;
88
89     /* Give the PHY time to reset */
90     HAL_DELAY_US(10000);
91
92     /* Clear the reset bit */
93     *fpga_vers = value & ~ETH_RST_MASK;
94   }
95 #else
96   // active low FETHIEN on BSCR1, assert reset low
97   pBCSR->bcsr1 &= ~(FETHIEN_ | FETHRST_);  
98   // de-assert reset
99   pBCSR->bcsr1 |= FETHRST_;  
100 #endif
101 }
102
103
104 /*-------------------------------------------------------------------
105 *
106 * FUNCTION NAME: 
107 *
108 * DESCRIPTION: Writes parameters to the control registers of LXT970
109 *
110 * EXTERNAL EFFECT:
111 *
112 * PARAMETERS:
113 *
114 * RETURNS: None
115 *
116 * ASSUMPTIONS:
117 *
118 *-------------------------------------------------------------------*/
119 UINT16 
120 InitEthernetPHY(VUINT32* pdir, VUINT32* pdat, UINT16 link)
121 {
122
123   VUINT16 FrameValue;
124   
125   /* 8101 Ethernet Management Pin Assignments */
126   pPortDir = pdir;
127   pPortData = pdat;
128   
129   (*pPortDir) |= MDC_PIN_MASK;   /* MD_Clock will always be output only */
130   
131   /* Test MDC & MDIO Pin Connection to PHY */
132   MdioFrame(WRITE, 0, MIRROR_REG, MD_TEST_FRAME); //send test frame
133   MdioFrame(WRITE, 0, MIRROR_REG, MD_TEST_FRAME); //send test frame
134   FrameValue = MdioFrame(READ, 0, MIRROR_REG, 0); //read test frame
135
136   if (FrameValue != MD_TEST_FRAME) 
137     return LINKERROR;   //test data integrity
138   
139   /* General Configuration */
140   MdioFrame(WRITE, 0, CONFIG_REG, 0x0000);  
141
142   if(link == HUNDRED_HD)
143       MdioFrame(WRITE, 0, AUTONEG_AD_REG, 0x0081); //100 Mbps Half, 802.3
144   else
145       MdioFrame(WRITE, 0, AUTONEG_AD_REG, 0x0021); //10  Mbps Half, 802.3
146
147   // 100 Mbps full duplex not supported
148   // MdioFrame(WRITE, 0, AUTONEG_AD_REG, 0x0101); //100 Mbps Full, 802.3
149
150   MdioFrame(WRITE, 0, CONTROL_REG, 0x1300);
151
152   return 0;
153 }
154
155 /*-------------------------------------------------------------------
156 *
157 * FUNCTION NAME: 
158 *
159 * DESCRIPTION:
160 *
161 * EXTERNAL EFFECT:
162 *
163 * PARAMETERS:
164 *
165 * RETURNS: None
166 *
167 * ASSUMPTIONS:
168 *
169 *-------------------------------------------------------------------*/
170 UINT16 
171 EthernetPHYInterruptHandler()
172 {                
173   // Reading registers 1 and 18 in sequence 
174   // clears the transceiver interrupt
175
176   MdioFrame(READ, 0, STATUS_REG, 0);    
177   MdioFrame(READ, 0, INT_STAT_REG, 0);  
178   
179   return LinkTestPHY();
180 } /* end EthernetPHYInterruptHandler */
181
182 /*-------------------------------------------------------------------
183 *
184 * FUNCTION NAME: 
185 *
186 * DESCRIPTION:
187 *
188 * EXTERNAL EFFECT:
189 *
190 * PARAMETERS:
191 *
192 * RETURNS: None
193 *
194 * ASSUMPTIONS:
195 *
196 *-------------------------------------------------------------------*/
197 UINT16 
198 LinkTestPHY()
199 {
200   UINT32 j;
201   UINT16 FrameValue = 0;
202
203   for (j = 0; j < 50; j++) {
204
205     HAL_DELAY_US(100000);
206   
207     FrameValue = MdioFrame(READ,0,CHIP_STAT_REG,0);  
208   
209     if ( (FrameValue & 0x0200) != 0 ) 
210       break;
211   }
212
213   FrameValue &= 0x3800;
214
215   switch (FrameValue) {
216     
217     case 0x3800: return HUNDRED_FD;
218     case 0x2800: return HUNDRED_HD;
219     case 0x3000: return TEN_FD;
220     case 0x2000: return TEN_HD;
221     default:     return NOTLINKED;
222   }
223
224 }
225
226 /*-------------------------------------------------------------------
227 *
228 * FUNCTION NAME: 
229 *
230 * DESCRIPTION:
231 *
232 * EXTERNAL EFFECT:
233 *
234 * PARAMETERS:
235 *
236 * RETURNS: None
237 *
238 * ASSUMPTIONS:
239 *
240 *-------------------------------------------------------------------*/
241 void EnablePHYinterrupt(UINT8 enable)
242 {
243   MdioFrame(WRITE, 0, INT_EN_REG, enable?0x2:0x0);
244 }
245
246 /*----------------------------------------------------------------------
247 *
248 * FUNCTION NAME: 
249 *
250 * DESCRIPTION: generic READ/WRITE function of LXT970 
251 *              through the MDC/MDIO interface.
252 *
253 * EXTERNAL EFFECT:
254 *
255 * PARAMETERS:
256 *
257 * RETURNS: None
258 *
259 * ASSUMPTIONS:
260 *
261 *---------------------------------------------------------------------*/
262 UINT16 
263 MdioFrame(MDIORW R_W, UINT16 PhyAddr, UINT16 RegAddr, UINT32 PutData) {
264
265   UINT16 GetData;
266
267   *pPortDir |= MDIO_PIN_MASK;   //set to output mode
268   
269   MdioSend(0xFFFFFFFF,32);      //PreAmble
270   MdioSend(0x1,2);              //Start Frame Delimiter
271   if (R_W==READ)
272     MdioSend(0x2,2);            //Read OpCode
273   else
274     MdioSend(0x1,2);            //Write OpCode
275   
276   MdioSend(PhyAddr,5);         //Send PHY transciever Address
277   MdioSend(RegAddr,5);         //Send Register Address
278
279   if (R_W==READ) {
280     *pPortDir &= ~MDIO_PIN_MASK;  //set to input mode
281     GetData = MdioReceive(17);    //Drive TurnAround and Data
282     MdioReceive(2);
283   }
284   else {
285     MdioSend(0x2,2);              //Drive TurnAround
286     MdioSend(PutData, 16);        //Send Data
287     GetData = 0;
288     *pPortDir &= ~MDIO_PIN_MASK;  //set to input mode
289   }
290
291   return GetData;
292
293 }
294 /*----------------------------------------------------------------------
295 *
296 * FUNCTION NAME: 
297 *
298 * DESCRIPTION:  Shift out  bits of data
299 *
300 * EXTERNAL EFFECT:
301 *
302 * PARAMETERS:
303 *
304 * RETURNS: None
305 *
306 * ASSUMPTIONS:
307 *
308 *----------------------------------------------------------------------*/
309 void 
310 MdioSend(UINT32 txF, UINT16 size) {
311
312   UINT32 dmask;
313   INT_NATIVE i, j; 
314
315   dmask = 1 << (size-1);            // msbit out first
316
317   for (i = 0; i < size; i++) {      // for "size" bits
318     
319     if ( txF & dmask )              //output data bit high
320       *pPortData |=  MDIO_PIN_MASK;
321     else                            //output data bit low > 400ns
322       *pPortData &= ~MDIO_PIN_MASK;
323                                         // >10ns       
324     *pPortData |= MDC_PIN_MASK;         // clock rise
325     
326     txF = (UINT32)(txF << 1);           // >160ns
327     
328     for (j=0; j<MDC_HOLD_TIME; j++);
329
330     *pPortData &= ~MDC_PIN_MASK;        // clock fall 
331
332     for (j=0; j<MDC_HOLD_TIME; j++);
333
334   } 
335   
336   return;
337 }
338  
339
340 /*---------------------------------------------------------------------
341 *
342 * FUNCTION NAME:
343 *
344 * DESCRIPTION:  Shifts in bits of data
345 *
346 * EXTERNAL EFFECT:
347 *
348 * PARAMETERS:
349 *
350 * RETURNS:
351 *
352 * ASSUMPTIONS:
353 *
354 *---------------------------------------------------------------------*/
355 UINT16 
356 MdioReceive(UINT16 size) {
357
358   UINT16 i,j, rxF = 0;
359
360   for (i = 0; i < size; i++) {   // 16 bits
361         
362     *pPortData |= MDC_PIN_MASK;            // clock rise
363
364     if ( *pPortData & MDIO_PIN_MASK )             // if read in a high bit
365       rxF = ( (UINT16)(rxF << 1) | 1 );           // shift in a one
366     else                                          // if read in a low bit
367       rxF = ( (UINT16)(rxF << 1) & ~(UINT16)1 );  // shift in a zero
368
369         
370     for (j=0; j<MDC_HOLD_TIME; j++);
371
372     *pPortData &= ~MDC_PIN_MASK;          // clock fall         
373
374     for (j=0; j<MDC_HOLD_TIME; j++);
375
376   } 
377   
378   return rxF;
379 }
380