]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/ns9750_eth.c
Merge with git://git.kernel.org/pub/scm/boot/u-boot/u-boot.git#pci
[people/ms/u-boot.git] / drivers / ns9750_eth.c
1 /***********************************************************************
2 *
3 * Copyright (C) 2004 by FS Forth-Systeme GmbH.
4 * All rights reserved.
5 *
6 * $Id: ns9750_eth.c,v 1.2 2004/02/24 14:09:39 mpietrek Exp $
7 * @Author: Markus Pietrek
8 * @Descr: Ethernet driver for the NS9750. Uses DMA Engine with polling
9 * interrupt status. But interrupts are not enabled.
10 * Only one tx buffer descriptor and the RXA buffer descriptor are used
11 * Currently no transmit lockup handling is included. eth_send has a 5s
12 * timeout for sending frames. No retransmits are performed when an
13 * error occurs.
14 * @References: [1] NS9750 Hardware Reference, December 2003
15 * [2] Intel LXT971 Datasheet #249414 Rev. 02
16 * [3] NS7520 Linux Ethernet Driver
17 *
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License as
20 * published by the Free Software Foundation; either version 2 of
21 * the License, or (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
31 * MA 02111-1307 USA
32 *
33 ***********************************************************************/
34
35 #include <common.h>
36 #include <net.h> /* NetSendPacket */
37
38 #include "ns9750_eth.h" /* for Ethernet and PHY */
39
40 #ifdef CONFIG_DRIVER_NS9750_ETHERNET
41
42 /* some definition to make transistion to linux easier */
43
44 #define NS9750_DRIVER_NAME "eth"
45 #define KERN_WARNING "Warning:"
46 #define KERN_ERR "Error:"
47 #define KERN_INFO "Info:"
48
49 #if 0
50 # define DEBUG
51 #endif
52
53 #ifdef DEBUG
54 # define printk printf
55
56 # define DEBUG_INIT 0x0001
57 # define DEBUG_MINOR 0x0002
58 # define DEBUG_RX 0x0004
59 # define DEBUG_TX 0x0008
60 # define DEBUG_INT 0x0010
61 # define DEBUG_POLL 0x0020
62 # define DEBUG_LINK 0x0040
63 # define DEBUG_MII 0x0100
64 # define DEBUG_MII_LOW 0x0200
65 # define DEBUG_MEM 0x0400
66 # define DEBUG_ERROR 0x4000
67 # define DEBUG_ERROR_CRIT 0x8000
68
69 static int nDebugLvl = DEBUG_ERROR_CRIT;
70
71 # define DEBUG_ARGS0( FLG, a0 ) if( ( nDebugLvl & (FLG) ) == (FLG) ) \
72 printf("%s: " a0, __FUNCTION__, 0, 0, 0, 0, 0, 0 )
73 # define DEBUG_ARGS1( FLG, a0, a1 ) if( ( nDebugLvl & (FLG) ) == (FLG)) \
74 printf("%s: " a0, __FUNCTION__, (int)(a1), 0, 0, 0, 0, 0 )
75 # define DEBUG_ARGS2( FLG, a0, a1, a2 ) if( (nDebugLvl & (FLG)) ==(FLG))\
76 printf("%s: " a0, __FUNCTION__, (int)(a1), (int)(a2), 0, 0,0,0 )
77 # define DEBUG_ARGS3( FLG, a0, a1, a2, a3 ) if((nDebugLvl &(FLG))==(FLG))\
78 printf("%s: "a0,__FUNCTION__,(int)(a1),(int)(a2),(int)(a3),0,0,0)
79 # define DEBUG_FN( FLG ) if( (nDebugLvl & (FLG)) == (FLG) ) \
80 printf("\r%s:line %d\n", (int)__FUNCTION__, __LINE__, 0,0,0,0);
81 # define ASSERT( expr, func ) if( !( expr ) ) { \
82 printf( "Assertion failed! %s:line %d %s\n", \
83 (int)__FUNCTION__,__LINE__,(int)(#expr),0,0,0); \
84 func }
85 #else /* DEBUG */
86 # define printk(...)
87 # define DEBUG_ARGS0( FLG, a0 )
88 # define DEBUG_ARGS1( FLG, a0, a1 )
89 # define DEBUG_ARGS2( FLG, a0, a1, a2 )
90 # define DEBUG_ARGS3( FLG, a0, a1, a2, a3 )
91 # define DEBUG_FN( n )
92 # define ASSERT(expr, func)
93 #endif /* DEBUG */
94
95 #define NS9750_MII_NEG_DELAY (5*CFG_HZ) /* in s */
96 #define TX_TIMEOUT (5*CFG_HZ) /* in s */
97
98 /* @TODO move it to eeprom.h */
99 #define FS_EEPROM_AUTONEG_MASK 0x7
100 #define FS_EEPROM_AUTONEG_SPEED_MASK 0x1
101 #define FS_EEPROM_AUTONEG_SPEED_10 0x0
102 #define FS_EEPROM_AUTONEG_SPEED_100 0x1
103 #define FS_EEPROM_AUTONEG_DUPLEX_MASK 0x2
104 #define FS_EEPROM_AUTONEG_DUPLEX_HALF 0x0
105 #define FS_EEPROM_AUTONEG_DUPLEX_FULL 0x2
106 #define FS_EEPROM_AUTONEG_ENABLE_MASK 0x4
107 #define FS_EEPROM_AUTONEG_DISABLE 0x0
108 #define FS_EEPROM_AUTONEG_ENABLE 0x4
109
110 /* buffer descriptors taken from [1] p.306 */
111 typedef struct
112 {
113 unsigned int* punSrc;
114 unsigned int unLen; /* 11 bits */
115 unsigned int* punDest; /* unused */
116 union {
117 unsigned int unReg;
118 struct {
119 unsigned uStatus : 16;
120 unsigned uRes : 12;
121 unsigned uFull : 1;
122 unsigned uEnable : 1;
123 unsigned uInt : 1;
124 unsigned uWrap : 1;
125 } bits;
126 } s;
127 } rx_buffer_desc_t;
128
129 typedef struct
130 {
131 unsigned int* punSrc;
132 unsigned int unLen; /* 10 bits */
133 unsigned int* punDest; /* unused */
134 union {
135 unsigned int unReg; /* only 32bit accesses may done to NS9750
136 * eth engine */
137 struct {
138 unsigned uStatus : 16;
139 unsigned uRes : 12;
140 unsigned uFull : 1;
141 unsigned uLast : 1;
142 unsigned uInt : 1;
143 unsigned uWrap : 1;
144 } bits;
145 } s;
146 } tx_buffer_desc_t;
147
148 static int ns9750_eth_reset( void );
149
150 static void ns9750_link_force( void );
151 static void ns9750_link_auto_negotiate( void );
152 static void ns9750_link_update_egcr( void );
153 static void ns9750_link_print_changed( void );
154
155 /* the PHY stuff */
156
157 static char ns9750_mii_identify_phy( void );
158 static unsigned short ns9750_mii_read( unsigned short uiRegister );
159 static void ns9750_mii_write( unsigned short uiRegister, unsigned short uiData );
160 static unsigned int ns9750_mii_get_clock_divisor( unsigned int unMaxMDIOClk );
161 static unsigned int ns9750_mii_poll_busy( void );
162
163 static unsigned int nPhyMaxMdioClock = PHY_MDIO_MAX_CLK;
164 static unsigned char ucLinkMode = FS_EEPROM_AUTONEG_ENABLE;
165 static unsigned int uiLastLinkStatus;
166 static PhyType phyDetected = PHY_NONE;
167
168 /* we use only one tx buffer descriptor */
169 static tx_buffer_desc_t* pTxBufferDesc =
170 (tx_buffer_desc_t*) get_eth_reg_addr( NS9750_ETH_TXBD );
171
172 /* we use only one rx buffer descriptor of the 4 */
173 static rx_buffer_desc_t aRxBufferDesc[ 4 ];
174
175 /***********************************************************************
176 * @Function: eth_init
177 * @Return: -1 on failure otherwise 0
178 * @Descr: Initializes the ethernet engine and uses either FS Forth's default
179 * MAC addr or the one in environment
180 ***********************************************************************/
181
182 int eth_init (bd_t * pbis)
183 {
184 /* This default MAC Addr is reserved by FS Forth-Systeme for the case of
185 EEPROM failures */
186 unsigned char aucMACAddr[6] = { 0x00, 0x04, 0xf3, 0x00, 0x06, 0x35 };
187 char *pcTmp = getenv ("ethaddr");
188 char *pcEnd;
189 int i;
190
191 DEBUG_FN (DEBUG_INIT);
192
193 /* no need to check for hardware */
194
195 if (!ns9750_eth_reset ())
196 return -1;
197
198 if (pcTmp != NULL)
199 for (i = 0; i < 6; i++) {
200 aucMACAddr[i] =
201 pcTmp ? simple_strtoul (pcTmp, &pcEnd,
202 16) : 0;
203 pcTmp = (*pcTmp) ? pcEnd + 1 : pcEnd;
204 }
205
206 /* configure ethernet address */
207
208 *get_eth_reg_addr (NS9750_ETH_SA1) =
209 aucMACAddr[5] << 8 | aucMACAddr[4];
210 *get_eth_reg_addr (NS9750_ETH_SA2) =
211 aucMACAddr[3] << 8 | aucMACAddr[2];
212 *get_eth_reg_addr (NS9750_ETH_SA3) =
213 aucMACAddr[1] << 8 | aucMACAddr[0];
214
215 /* enable hardware */
216
217 *get_eth_reg_addr (NS9750_ETH_MAC1) = NS9750_ETH_MAC1_RXEN;
218
219 /* the linux kernel may give packets < 60 bytes, for example arp */
220 *get_eth_reg_addr (NS9750_ETH_MAC2) = NS9750_ETH_MAC2_CRCEN |
221 NS9750_ETH_MAC2_PADEN | NS9750_ETH_MAC2_HUGE;
222
223 /* enable receive and transmit FIFO, use 10/100 Mbps MII */
224 *get_eth_reg_addr (NS9750_ETH_EGCR1) =
225 NS9750_ETH_EGCR1_ETXWM |
226 NS9750_ETH_EGCR1_ERX |
227 NS9750_ETH_EGCR1_ERXDMA |
228 NS9750_ETH_EGCR1_ETX |
229 NS9750_ETH_EGCR1_ETXDMA | NS9750_ETH_EGCR1_ITXA;
230
231 /* prepare DMA descriptors */
232 for (i = 0; i < 4; i++) {
233 aRxBufferDesc[i].punSrc = 0;
234 aRxBufferDesc[i].unLen = 0;
235 aRxBufferDesc[i].s.bits.uWrap = 1;
236 aRxBufferDesc[i].s.bits.uInt = 1;
237 aRxBufferDesc[i].s.bits.uEnable = 0;
238 aRxBufferDesc[i].s.bits.uFull = 0;
239 }
240
241 /* NetRxPackets[ 0 ] is initialized before eth_init is called and never
242 changes. NetRxPackets is 32bit aligned */
243 aRxBufferDesc[0].punSrc = (unsigned int *) NetRxPackets[0];
244 aRxBufferDesc[0].s.bits.uEnable = 1;
245 aRxBufferDesc[0].unLen = 1522; /* as stated in [1] p.307 */
246
247 *get_eth_reg_addr (NS9750_ETH_RXAPTR) =
248 (unsigned int) &aRxBufferDesc[0];
249
250 /* [1] Tab. 221 states less than 5us */
251 *get_eth_reg_addr (NS9750_ETH_EGCR1) |= NS9750_ETH_EGCR1_ERXINIT;
252 while (!
253 (*get_eth_reg_addr (NS9750_ETH_EGSR) & NS9750_ETH_EGSR_RXINIT))
254 /* wait for finish */
255 udelay (1);
256
257 /* @TODO do we need to clear RXINIT? */
258 *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~NS9750_ETH_EGCR1_ERXINIT;
259
260 *get_eth_reg_addr (NS9750_ETH_RXFREE) = 0x1;
261
262 return 0;
263 }
264
265 /***********************************************************************
266 * @Function: eth_send
267 * @Return: -1 on timeout otherwise 1
268 * @Descr: sends one frame by DMA
269 ***********************************************************************/
270
271 int eth_send (volatile void *pPacket, int nLen)
272 {
273 ulong ulTimeout;
274
275 DEBUG_FN (DEBUG_TX);
276
277 /* clear old status values */
278 *get_eth_reg_addr (NS9750_ETH_EINTR) &=
279 *get_eth_reg_addr (NS9750_ETH_EINTR) & NS9750_ETH_EINTR_TX_MA;
280
281 /* prepare Tx Descriptors */
282
283 pTxBufferDesc->punSrc = (unsigned int *) pPacket; /* pPacket is 32bit
284 * aligned */
285 pTxBufferDesc->unLen = nLen;
286 /* only 32bit accesses allowed. wrap, full, interrupt and enabled to 1 */
287 pTxBufferDesc->s.unReg = 0xf0000000;
288 /* pTxBufferDesc is the first possible buffer descriptor */
289 *get_eth_reg_addr (NS9750_ETH_TXPTR) = 0x0;
290
291 /* enable processor for next frame */
292
293 *get_eth_reg_addr (NS9750_ETH_EGCR2) &= ~NS9750_ETH_EGCR2_TCLER;
294 *get_eth_reg_addr (NS9750_ETH_EGCR2) |= NS9750_ETH_EGCR2_TCLER;
295
296 ulTimeout = get_timer (0);
297
298 DEBUG_ARGS0 (DEBUG_TX | DEBUG_MINOR,
299 "Waiting for transmission to finish\n");
300 while (!
301 (*get_eth_reg_addr (NS9750_ETH_EINTR) &
302 (NS9750_ETH_EINTR_TXDONE | NS9750_ETH_EINTR_TXERR))) {
303 /* do nothing, wait for completion */
304 if (get_timer (0) - ulTimeout > TX_TIMEOUT) {
305 DEBUG_ARGS0 (DEBUG_TX, "Transmit Timed out\n");
306 return -1;
307 }
308 }
309 DEBUG_ARGS0 (DEBUG_TX | DEBUG_MINOR, "transmitted...\n");
310
311 return 0;
312 }
313
314 /***********************************************************************
315 * @Function: eth_rx
316 * @Return: size of last frame in bytes or 0 if no frame available
317 * @Descr: gives one frame to U-Boot which has been copied by DMA engine already
318 * to NetRxPackets[ 0 ].
319 ***********************************************************************/
320
321 int eth_rx (void)
322 {
323 int nLen = 0;
324 unsigned int unStatus;
325
326 unStatus =
327 *get_eth_reg_addr (NS9750_ETH_EINTR) & NS9750_ETH_EINTR_RX_MA;
328
329 if (!unStatus)
330 /* no packet available, return immediately */
331 return 0;
332
333 DEBUG_FN (DEBUG_RX);
334
335 /* unLen always < max(nLen) and discard checksum */
336 nLen = (int) aRxBufferDesc[0].unLen - 4;
337
338 /* acknowledge status register */
339 *get_eth_reg_addr (NS9750_ETH_EINTR) = unStatus;
340
341 aRxBufferDesc[0].unLen = 1522;
342 aRxBufferDesc[0].s.bits.uFull = 0;
343
344 /* Buffer A descriptor available again */
345 *get_eth_reg_addr (NS9750_ETH_RXFREE) |= 0x1;
346
347 /* NetReceive may call eth_send. Due to a possible bug of the NS9750 we
348 * have to acknowledge the received frame before sending a new one */
349 if (unStatus & NS9750_ETH_EINTR_RXDONEA)
350 NetReceive (NetRxPackets[0], nLen);
351
352 return nLen;
353 }
354
355 /***********************************************************************
356 * @Function: eth_halt
357 * @Return: n/a
358 * @Descr: stops the ethernet engine
359 ***********************************************************************/
360
361 void eth_halt (void)
362 {
363 DEBUG_FN (DEBUG_INIT);
364
365 *get_eth_reg_addr (NS9750_ETH_MAC1) &= ~NS9750_ETH_MAC1_RXEN;
366 *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~(NS9750_ETH_EGCR1_ERX |
367 NS9750_ETH_EGCR1_ERXDMA |
368 NS9750_ETH_EGCR1_ETX |
369 NS9750_ETH_EGCR1_ETXDMA);
370 }
371
372 /***********************************************************************
373 * @Function: ns9750_eth_reset
374 * @Return: 0 on failure otherwise 1
375 * @Descr: resets the ethernet interface and the PHY,
376 * performs auto negotiation or fixed modes
377 ***********************************************************************/
378
379 static int ns9750_eth_reset (void)
380 {
381 DEBUG_FN (DEBUG_MINOR);
382
383 /* Reset MAC */
384 *get_eth_reg_addr (NS9750_ETH_EGCR1) |= NS9750_ETH_EGCR1_MAC_HRST;
385 udelay (5); /* according to [1], p.322 */
386 *get_eth_reg_addr (NS9750_ETH_EGCR1) &= ~NS9750_ETH_EGCR1_MAC_HRST;
387
388 /* reset and initialize PHY */
389
390 *get_eth_reg_addr (NS9750_ETH_MAC1) &= ~NS9750_ETH_MAC1_SRST;
391
392 /* we don't support hot plugging of PHY, therefore we don't reset
393 phyDetected and nPhyMaxMdioClock here. The risk is if the setting is
394 incorrect the first open
395 may detect the PHY correctly but succeding will fail
396 For reseting the PHY and identifying we have to use the standard
397 MDIO CLOCK value 2.5 MHz only after hardware reset
398 After having identified the PHY we will do faster */
399
400 *get_eth_reg_addr (NS9750_ETH_MCFG) =
401 ns9750_mii_get_clock_divisor (nPhyMaxMdioClock);
402
403 /* reset PHY */
404 ns9750_mii_write (PHY_COMMON_CTRL, PHY_COMMON_CTRL_RESET);
405 ns9750_mii_write (PHY_COMMON_CTRL, 0);
406
407 /* @TODO check time */
408 udelay (3000); /* [2] p.70 says at least 300us reset recovery time. But
409 go sure, it didn't worked stable at higher timer
410 frequencies under LxNETES-2.x */
411
412 /* MII clock has been setup to default, ns9750_mii_identify_phy should
413 work for all */
414
415 if (!ns9750_mii_identify_phy ()) {
416 printk (KERN_ERR NS9750_DRIVER_NAME
417 ": Unsupported PHY, aborting\n");
418 return 0;
419 }
420
421 /* now take the highest MDIO clock possible after detection */
422 *get_eth_reg_addr (NS9750_ETH_MCFG) =
423 ns9750_mii_get_clock_divisor (nPhyMaxMdioClock);
424
425
426 /* PHY has been detected, so there can be no abort reason and we can
427 finish initializing ethernet */
428
429 uiLastLinkStatus = 0xff; /* undefined */
430
431 if ((ucLinkMode & FS_EEPROM_AUTONEG_ENABLE_MASK) ==
432 FS_EEPROM_AUTONEG_DISABLE)
433 /* use parameters defined */
434 ns9750_link_force ();
435 else
436 ns9750_link_auto_negotiate ();
437
438 if (phyDetected == PHY_LXT971A)
439 /* set LED2 to link mode */
440 ns9750_mii_write (PHY_LXT971_LED_CFG,
441 PHY_LXT971_LED_CFG_LINK_ACT <<
442 PHY_LXT971_LED_CFG_SHIFT_LED2);
443
444 return 1;
445 }
446
447 /***********************************************************************
448 * @Function: ns9750_link_force
449 * @Return: void
450 * @Descr: configures eth and MII to use the link mode defined in
451 * ucLinkMode
452 ***********************************************************************/
453
454 static void ns9750_link_force (void)
455 {
456 unsigned short uiControl;
457
458 DEBUG_FN (DEBUG_LINK);
459
460 uiControl = ns9750_mii_read (PHY_COMMON_CTRL);
461 uiControl &= ~(PHY_COMMON_CTRL_SPD_MA |
462 PHY_COMMON_CTRL_AUTO_NEG | PHY_COMMON_CTRL_DUPLEX);
463
464 uiLastLinkStatus = 0;
465
466 if ((ucLinkMode & FS_EEPROM_AUTONEG_SPEED_MASK) ==
467 FS_EEPROM_AUTONEG_SPEED_100) {
468 uiControl |= PHY_COMMON_CTRL_SPD_100;
469 uiLastLinkStatus |= PHY_LXT971_STAT2_100BTX;
470 } else
471 uiControl |= PHY_COMMON_CTRL_SPD_10;
472
473 if ((ucLinkMode & FS_EEPROM_AUTONEG_DUPLEX_MASK) ==
474 FS_EEPROM_AUTONEG_DUPLEX_FULL) {
475 uiControl |= PHY_COMMON_CTRL_DUPLEX;
476 uiLastLinkStatus |= PHY_LXT971_STAT2_DUPLEX_MODE;
477 }
478
479 ns9750_mii_write (PHY_COMMON_CTRL, uiControl);
480
481 ns9750_link_print_changed ();
482 ns9750_link_update_egcr ();
483 }
484
485 /***********************************************************************
486 * @Function: ns9750_link_auto_negotiate
487 * @Return: void
488 * @Descr: performs auto-negotation of link.
489 ***********************************************************************/
490
491 static void ns9750_link_auto_negotiate (void)
492 {
493 unsigned long ulStartJiffies;
494 unsigned short uiStatus;
495
496 DEBUG_FN (DEBUG_LINK);
497
498 /* run auto-negotation */
499 /* define what we are capable of */
500 ns9750_mii_write (PHY_COMMON_AUTO_ADV,
501 PHY_COMMON_AUTO_ADV_100BTXFD |
502 PHY_COMMON_AUTO_ADV_100BTX |
503 PHY_COMMON_AUTO_ADV_10BTFD |
504 PHY_COMMON_AUTO_ADV_10BT |
505 PHY_COMMON_AUTO_ADV_802_3);
506 /* start auto-negotiation */
507 ns9750_mii_write (PHY_COMMON_CTRL,
508 PHY_COMMON_CTRL_AUTO_NEG |
509 PHY_COMMON_CTRL_RES_AUTO);
510
511 /* wait for completion */
512
513 ulStartJiffies = get_ticks ();
514 while (get_ticks () < ulStartJiffies + NS9750_MII_NEG_DELAY) {
515 uiStatus = ns9750_mii_read (PHY_COMMON_STAT);
516 if ((uiStatus &
517 (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) ==
518 (PHY_COMMON_STAT_AN_COMP | PHY_COMMON_STAT_LNK_STAT)) {
519 /* lucky we are, auto-negotiation succeeded */
520 ns9750_link_print_changed ();
521 ns9750_link_update_egcr ();
522 return;
523 }
524 }
525
526 DEBUG_ARGS0 (DEBUG_LINK, "auto-negotiation timed out\n");
527 /* ignore invalid link settings */
528 }
529
530 /***********************************************************************
531 * @Function: ns9750_link_update_egcr
532 * @Return: void
533 * @Descr: updates the EGCR and MAC2 link status after mode change or
534 * auto-negotation
535 ***********************************************************************/
536
537 static void ns9750_link_update_egcr (void)
538 {
539 unsigned int unEGCR;
540 unsigned int unMAC2;
541 unsigned int unIPGT;
542
543 DEBUG_FN (DEBUG_LINK);
544
545 unEGCR = *get_eth_reg_addr (NS9750_ETH_EGCR1);
546 unMAC2 = *get_eth_reg_addr (NS9750_ETH_MAC2);
547 unIPGT = *get_eth_reg_addr (NS9750_ETH_IPGT) & ~NS9750_ETH_IPGT_MA;
548
549 unMAC2 &= ~NS9750_ETH_MAC2_FULLD;
550 if ((uiLastLinkStatus & PHY_LXT971_STAT2_DUPLEX_MODE)
551 == PHY_LXT971_STAT2_DUPLEX_MODE) {
552 unMAC2 |= NS9750_ETH_MAC2_FULLD;
553 unIPGT |= 0x15; /* see [1] p. 339 */
554 } else
555 unIPGT |= 0x12; /* see [1] p. 339 */
556
557 *get_eth_reg_addr (NS9750_ETH_MAC2) = unMAC2;
558 *get_eth_reg_addr (NS9750_ETH_EGCR1) = unEGCR;
559 *get_eth_reg_addr (NS9750_ETH_IPGT) = unIPGT;
560 }
561
562 /***********************************************************************
563 * @Function: ns9750_link_print_changed
564 * @Return: void
565 * @Descr: checks whether the link status has changed and if so prints
566 * the new mode
567 ***********************************************************************/
568
569 static void ns9750_link_print_changed (void)
570 {
571 unsigned short uiStatus;
572 unsigned short uiControl;
573
574 DEBUG_FN (DEBUG_LINK);
575
576 uiControl = ns9750_mii_read (PHY_COMMON_CTRL);
577
578 if ((uiControl & PHY_COMMON_CTRL_AUTO_NEG) ==
579 PHY_COMMON_CTRL_AUTO_NEG) {
580 /* PHY_COMMON_STAT_LNK_STAT is only set on autonegotiation */
581 uiStatus = ns9750_mii_read (PHY_COMMON_STAT);
582
583 if (!(uiStatus & PHY_COMMON_STAT_LNK_STAT)) {
584 printk (KERN_WARNING NS9750_DRIVER_NAME
585 ": link down\n");
586 /* @TODO Linux: carrier_off */
587 } else {
588 /* @TODO Linux: carrier_on */
589 if (phyDetected == PHY_LXT971A) {
590 uiStatus = ns9750_mii_read (PHY_LXT971_STAT2);
591 uiStatus &= (PHY_LXT971_STAT2_100BTX |
592 PHY_LXT971_STAT2_DUPLEX_MODE |
593 PHY_LXT971_STAT2_AUTO_NEG);
594
595 /* mask out all uninteresting parts */
596 }
597 /* other PHYs must store there link information in
598 uiStatus as PHY_LXT971 */
599 }
600 } else {
601 /* mode has been forced, so uiStatus should be the same as the
602 last link status, enforce printing */
603 uiStatus = uiLastLinkStatus;
604 uiLastLinkStatus = 0xff;
605 }
606
607 if (uiStatus != uiLastLinkStatus) {
608 /* save current link status */
609 uiLastLinkStatus = uiStatus;
610
611 /* print new link status */
612
613 printk (KERN_INFO NS9750_DRIVER_NAME
614 ": link mode %i Mbps %s duplex %s\n",
615 (uiStatus & PHY_LXT971_STAT2_100BTX) ? 100 : 10,
616 (uiStatus & PHY_LXT971_STAT2_DUPLEX_MODE) ? "full" :
617 "half",
618 (uiStatus & PHY_LXT971_STAT2_AUTO_NEG) ? "(auto)" :
619 "");
620 }
621 }
622
623 /***********************************************************************
624 * the MII low level stuff
625 ***********************************************************************/
626
627 /***********************************************************************
628 * @Function: ns9750_mii_identify_phy
629 * @Return: 1 if supported PHY has been detected otherwise 0
630 * @Descr: checks for supported PHY and prints the IDs.
631 ***********************************************************************/
632
633 static char ns9750_mii_identify_phy (void)
634 {
635 unsigned short uiID1;
636 unsigned short uiID2;
637 unsigned char *szName;
638 char cRes = 0;
639
640 DEBUG_FN (DEBUG_MII);
641
642 phyDetected = (PhyType) uiID1 = ns9750_mii_read (PHY_COMMON_ID1);
643
644 switch (phyDetected) {
645 case PHY_LXT971A:
646 szName = "LXT971A";
647 uiID2 = ns9750_mii_read (PHY_COMMON_ID2);
648 nPhyMaxMdioClock = PHY_LXT971_MDIO_MAX_CLK;
649 cRes = 1;
650 break;
651 case PHY_NONE:
652 default:
653 /* in case uiID1 == 0 && uiID2 == 0 we may have the wrong
654 address or reset sets the wrong NS9750_ETH_MCFG_CLKS */
655
656 uiID2 = 0;
657 szName = "unknown";
658 nPhyMaxMdioClock = PHY_MDIO_MAX_CLK;
659 phyDetected = PHY_NONE;
660 }
661
662 printk (KERN_INFO NS9750_DRIVER_NAME
663 ": PHY (0x%x, 0x%x) = %s detected\n", uiID1, uiID2, szName);
664
665 return cRes;
666 }
667
668 /***********************************************************************
669 * @Function: ns9750_mii_read
670 * @Return: the data read from PHY register uiRegister
671 * @Descr: the data read may be invalid if timed out. If so, a message
672 * is printed but the invalid data is returned.
673 * The fixed device address is being used.
674 ***********************************************************************/
675
676 static unsigned short ns9750_mii_read (unsigned short uiRegister)
677 {
678 DEBUG_FN (DEBUG_MII_LOW);
679
680 /* write MII register to be read */
681 *get_eth_reg_addr (NS9750_ETH_MADR) =
682 NS9750_ETH_PHY_ADDRESS << 8 | uiRegister;
683
684 *get_eth_reg_addr (NS9750_ETH_MCMD) = NS9750_ETH_MCMD_READ;
685
686 if (!ns9750_mii_poll_busy ())
687 printk (KERN_WARNING NS9750_DRIVER_NAME
688 ": MII still busy in read\n");
689 /* continue to read */
690
691 *get_eth_reg_addr (NS9750_ETH_MCMD) = 0;
692
693 return (unsigned short) (*get_eth_reg_addr (NS9750_ETH_MRDD));
694 }
695
696
697 /***********************************************************************
698 * @Function: ns9750_mii_write
699 * @Return: nothing
700 * @Descr: writes the data to the PHY register. In case of a timeout,
701 * no special handling is performed but a message printed
702 * The fixed device address is being used.
703 ***********************************************************************/
704
705 static void ns9750_mii_write (unsigned short uiRegister,
706 unsigned short uiData)
707 {
708 DEBUG_FN (DEBUG_MII_LOW);
709
710 /* write MII register to be written */
711 *get_eth_reg_addr (NS9750_ETH_MADR) =
712 NS9750_ETH_PHY_ADDRESS << 8 | uiRegister;
713
714 *get_eth_reg_addr (NS9750_ETH_MWTD) = uiData;
715
716 if (!ns9750_mii_poll_busy ()) {
717 printf (KERN_WARNING NS9750_DRIVER_NAME
718 ": MII still busy in write\n");
719 }
720 }
721
722
723 /***********************************************************************
724 * @Function: ns9750_mii_get_clock_divisor
725 * @Return: the clock divisor that should be used in NS9750_ETH_MCFG_CLKS
726 * @Descr: if no clock divisor can be calculated for the
727 * current SYSCLK and the maximum MDIO Clock, a warning is printed
728 * and the greatest divisor is taken
729 ***********************************************************************/
730
731 static unsigned int ns9750_mii_get_clock_divisor (unsigned int unMaxMDIOClk)
732 {
733 struct {
734 unsigned int unSysClkDivisor;
735 unsigned int unClks; /* field for NS9750_ETH_MCFG_CLKS */
736 } PHYClockDivisors[] = {
737 {
738 4, NS9750_ETH_MCFG_CLKS_4}, {
739 6, NS9750_ETH_MCFG_CLKS_6}, {
740 8, NS9750_ETH_MCFG_CLKS_8}, {
741 10, NS9750_ETH_MCFG_CLKS_10}, {
742 20, NS9750_ETH_MCFG_CLKS_20}, {
743 30, NS9750_ETH_MCFG_CLKS_30}, {
744 40, NS9750_ETH_MCFG_CLKS_40}
745 };
746
747 int nIndexSysClkDiv;
748 int nArraySize =
749 sizeof (PHYClockDivisors) / sizeof (PHYClockDivisors[0]);
750 unsigned int unClks = NS9750_ETH_MCFG_CLKS_40; /* defaults to
751 greatest div */
752
753 DEBUG_FN (DEBUG_INIT);
754
755 for (nIndexSysClkDiv = 0; nIndexSysClkDiv < nArraySize;
756 nIndexSysClkDiv++) {
757 /* find first sysclock divisor that isn't higher than 2.5 MHz
758 clock */
759 if (AHB_CLK_FREQ /
760 PHYClockDivisors[nIndexSysClkDiv].unSysClkDivisor <=
761 unMaxMDIOClk) {
762 unClks = PHYClockDivisors[nIndexSysClkDiv].unClks;
763 break;
764 }
765 }
766
767 DEBUG_ARGS2 (DEBUG_INIT,
768 "Taking MDIO Clock bit mask 0x%0x for max clock %i\n",
769 unClks, unMaxMDIOClk);
770
771 /* return greatest divisor */
772 return unClks;
773 }
774
775 /***********************************************************************
776 * @Function: ns9750_mii_poll_busy
777 * @Return: 0 if timed out otherwise the remaing timeout
778 * @Descr: waits until the MII has completed a command or it times out
779 * code may be interrupted by hard interrupts.
780 * It is not checked what happens on multiple actions when
781 * the first is still being busy and we timeout.
782 ***********************************************************************/
783
784 static unsigned int ns9750_mii_poll_busy (void)
785 {
786 unsigned int unTimeout = 10000;
787
788 DEBUG_FN (DEBUG_MII_LOW);
789
790 while (((*get_eth_reg_addr (NS9750_ETH_MIND) & NS9750_ETH_MIND_BUSY)
791 == NS9750_ETH_MIND_BUSY) && unTimeout)
792 unTimeout--;
793
794 return unTimeout;
795 }
796
797 #endif /* CONFIG_DRIVER_NS9750_ETHERNET */