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