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 /* some definition to make transition to linux easier */
41 
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 
67 static 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 
93 #define NS9750_MII_NEG_DELAY		(5*CONFIG_SYS_HZ) /* in s */
94 #define TX_TIMEOUT			(5*CONFIG_SYS_HZ) /* in s */
95 
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 */
109 typedef 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 
127 typedef 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 
146 static int ns9750_eth_reset( void );
147 
148 static void ns9750_link_force( void );
149 static void ns9750_link_auto_negotiate( void );
150 static void ns9750_link_update_egcr( void );
151 static void ns9750_link_print_changed( void );
152 
153 /* the PHY stuff */
154 
155 static char ns9750_mii_identify_phy( void );
156 static unsigned short ns9750_mii_read( unsigned short uiRegister );
157 static void ns9750_mii_write( unsigned short uiRegister, unsigned short uiData );
158 static unsigned int ns9750_mii_get_clock_divisor( unsigned int unMaxMDIOClk );
159 static unsigned int ns9750_mii_poll_busy( void );
160 
161 static unsigned int nPhyMaxMdioClock = PHY_MDIO_MAX_CLK;
162 static unsigned char ucLinkMode =      FS_EEPROM_AUTONEG_ENABLE;
163 static unsigned int uiLastLinkStatus;
164 static PhyType phyDetected = PHY_NONE;
165 
166 /* we use only one tx buffer descriptor */
167 static 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 */
171 static 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 
eth_init(bd_t * pbis)180 int 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 
eth_send(volatile void * pPacket,int nLen)269 int 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 
eth_rx(void)319 int 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 
eth_halt(void)359 void 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 
ns9750_eth_reset(void)377 static 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 */
402 	ns9750_mii_write(PHY_BMCR, PHY_BMCR_RESET);
403 	ns9750_mii_write(PHY_BMCR, 0);
404 
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 
ns9750_link_force(void)452 static void ns9750_link_force (void)
453 {
454 	unsigned short uiControl;
455 
456 	DEBUG_FN (DEBUG_LINK);
457 
458 	uiControl = ns9750_mii_read(PHY_BMCR);
459 	uiControl &= ~(PHY_BMCR_SPEED_MASK |
460 		       PHY_BMCR_AUTON | PHY_BMCR_DPLX);
461 
462 	uiLastLinkStatus = 0;
463 
464 	if ((ucLinkMode & FS_EEPROM_AUTONEG_SPEED_MASK) ==
465 	    FS_EEPROM_AUTONEG_SPEED_100) {
466 		uiControl |= PHY_BMCR_100MB;
467 		uiLastLinkStatus |= PHY_LXT971_STAT2_100BTX;
468 	} else
469 		uiControl |= PHY_BMCR_10_MBPS;
470 
471 	if ((ucLinkMode & FS_EEPROM_AUTONEG_DUPLEX_MASK) ==
472 	    FS_EEPROM_AUTONEG_DUPLEX_FULL) {
473 		uiControl |= PHY_BMCR_DPLX;
474 		uiLastLinkStatus |= PHY_LXT971_STAT2_DUPLEX_MODE;
475 	}
476 
477 	ns9750_mii_write(PHY_BMCR, uiControl);
478 
479 	ns9750_link_print_changed ();
480 	ns9750_link_update_egcr ();
481 }
482 
483 /***********************************************************************
484  * @Function: ns9750_link_auto_negotiate
485  * @Return: void
486  * @Descr: performs auto-negotation of link.
487  ***********************************************************************/
488 
ns9750_link_auto_negotiate(void)489 static void ns9750_link_auto_negotiate (void)
490 {
491 	unsigned long ulStartJiffies;
492 	unsigned short uiStatus;
493 
494 	DEBUG_FN (DEBUG_LINK);
495 
496 	/* run auto-negotation */
497 	/* define what we are capable of */
498 	ns9750_mii_write(PHY_ANAR,
499 			 PHY_ANLPAR_TXFD |
500 			 PHY_ANLPAR_TX |
501 			 PHY_ANLPAR_10FD |
502 			 PHY_ANLPAR_10 |
503 			 PHY_ANLPAR_PSB_802_3);
504 	/* start auto-negotiation */
505 	ns9750_mii_write(PHY_BMCR, PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
506 
507 	/* wait for completion */
508 
509 	ulStartJiffies = get_ticks ();
510 	while (get_ticks () < ulStartJiffies + NS9750_MII_NEG_DELAY) {
511 		uiStatus = ns9750_mii_read(PHY_BMSR);
512 		if ((uiStatus &
513 		     (PHY_BMSR_AUTN_COMP | PHY_BMSR_LS)) ==
514 		    (PHY_BMSR_AUTN_COMP | PHY_BMSR_LS)) {
515 			/* lucky we are, auto-negotiation succeeded */
516 			ns9750_link_print_changed ();
517 			ns9750_link_update_egcr ();
518 			return;
519 		}
520 	}
521 
522 	DEBUG_ARGS0 (DEBUG_LINK, "auto-negotiation timed out\n");
523 	/* ignore invalid link settings */
524 }
525 
526 /***********************************************************************
527  * @Function: ns9750_link_update_egcr
528  * @Return: void
529  * @Descr: updates the EGCR and MAC2 link status after mode change or
530  *	   auto-negotation
531  ***********************************************************************/
532 
ns9750_link_update_egcr(void)533 static void ns9750_link_update_egcr (void)
534 {
535 	unsigned int unEGCR;
536 	unsigned int unMAC2;
537 	unsigned int unIPGT;
538 
539 	DEBUG_FN (DEBUG_LINK);
540 
541 	unEGCR = *get_eth_reg_addr (NS9750_ETH_EGCR1);
542 	unMAC2 = *get_eth_reg_addr (NS9750_ETH_MAC2);
543 	unIPGT = *get_eth_reg_addr (NS9750_ETH_IPGT) & ~NS9750_ETH_IPGT_MA;
544 
545 	unMAC2 &= ~NS9750_ETH_MAC2_FULLD;
546 	if ((uiLastLinkStatus & PHY_LXT971_STAT2_DUPLEX_MODE)
547 	    == PHY_LXT971_STAT2_DUPLEX_MODE) {
548 		unMAC2 |= NS9750_ETH_MAC2_FULLD;
549 		unIPGT |= 0x15; /* see [1] p. 339 */
550 	} else
551 		unIPGT |= 0x12; /* see [1] p. 339 */
552 
553 	*get_eth_reg_addr (NS9750_ETH_MAC2) = unMAC2;
554 	*get_eth_reg_addr (NS9750_ETH_EGCR1) = unEGCR;
555 	*get_eth_reg_addr (NS9750_ETH_IPGT) = unIPGT;
556 }
557 
558 /***********************************************************************
559  * @Function: ns9750_link_print_changed
560  * @Return: void
561  * @Descr: checks whether the link status has changed and if so prints
562  *	   the new mode
563  ***********************************************************************/
564 
ns9750_link_print_changed(void)565 static void ns9750_link_print_changed (void)
566 {
567 	unsigned short uiStatus;
568 	unsigned short uiControl;
569 
570 	DEBUG_FN (DEBUG_LINK);
571 
572 	uiControl = ns9750_mii_read(PHY_BMCR);
573 
574 	if ((uiControl & PHY_BMCR_AUTON) == PHY_BMCR_AUTON) {
575 		/* PHY_BMSR_LS is only set on autonegotiation */
576 		uiStatus = ns9750_mii_read(PHY_BMSR);
577 
578 		if (!(uiStatus & PHY_BMSR_LS)) {
579 			printk (KERN_WARNING NS9750_DRIVER_NAME
580 				": link down\n");
581 			/* @TODO Linux: carrier_off */
582 		} else {
583 			/* @TODO Linux: carrier_on */
584 			if (phyDetected == PHY_LXT971A) {
585 				uiStatus = ns9750_mii_read (PHY_LXT971_STAT2);
586 				uiStatus &= (PHY_LXT971_STAT2_100BTX |
587 					     PHY_LXT971_STAT2_DUPLEX_MODE |
588 					     PHY_LXT971_STAT2_AUTO_NEG);
589 
590 				/* mask out all uninteresting parts */
591 			}
592 			/* other PHYs must store their link information in
593 			   uiStatus as PHY_LXT971 */
594 		}
595 	} else {
596 		/* mode has been forced, so uiStatus should be the same as the
597 		   last link status, enforce printing */
598 		uiStatus = uiLastLinkStatus;
599 		uiLastLinkStatus = 0xff;
600 	}
601 
602 	if (uiStatus != uiLastLinkStatus) {
603 		/* save current link status */
604 		uiLastLinkStatus = uiStatus;
605 
606 		/* print new link status */
607 
608 		printk (KERN_INFO NS9750_DRIVER_NAME
609 			": link mode %i Mbps %s duplex %s\n",
610 			(uiStatus & PHY_LXT971_STAT2_100BTX) ? 100 : 10,
611 			(uiStatus & PHY_LXT971_STAT2_DUPLEX_MODE) ? "full" :
612 			"half",
613 			(uiStatus & PHY_LXT971_STAT2_AUTO_NEG) ? "(auto)" :
614 			"");
615 	}
616 }
617 
618 /***********************************************************************
619  * the MII low level stuff
620  ***********************************************************************/
621 
622 /***********************************************************************
623  * @Function: ns9750_mii_identify_phy
624  * @Return: 1 if supported PHY has been detected otherwise 0
625  * @Descr: checks for supported PHY and prints the IDs.
626  ***********************************************************************/
627 
ns9750_mii_identify_phy(void)628 static char ns9750_mii_identify_phy (void)
629 {
630 	unsigned short uiID1;
631 	unsigned short uiID2;
632 	unsigned char *szName;
633 	char cRes = 0;
634 
635 	DEBUG_FN (DEBUG_MII);
636 
637 	phyDetected = (PhyType) uiID1 = ns9750_mii_read(PHY_PHYIDR1);
638 
639 	switch (phyDetected) {
640 	case PHY_LXT971A:
641 		szName = "LXT971A";
642 		uiID2 = ns9750_mii_read(PHY_PHYIDR2);
643 		nPhyMaxMdioClock = PHY_LXT971_MDIO_MAX_CLK;
644 		cRes = 1;
645 		break;
646 	case PHY_NONE:
647 	default:
648 		/* in case uiID1 == 0 && uiID2 == 0 we may have the wrong
649 		   address or reset sets the wrong NS9750_ETH_MCFG_CLKS */
650 
651 		uiID2 = 0;
652 		szName = "unknown";
653 		nPhyMaxMdioClock = PHY_MDIO_MAX_CLK;
654 		phyDetected = PHY_NONE;
655 	}
656 
657 	printk (KERN_INFO NS9750_DRIVER_NAME
658 		": PHY (0x%x, 0x%x) = %s detected\n", uiID1, uiID2, szName);
659 
660 	return cRes;
661 }
662 
663 /***********************************************************************
664  * @Function: ns9750_mii_read
665  * @Return: the data read from PHY register uiRegister
666  * @Descr: the data read may be invalid if timed out. If so, a message
667  *	   is printed but the invalid data is returned.
668  *	   The fixed device address is being used.
669  ***********************************************************************/
670 
ns9750_mii_read(unsigned short uiRegister)671 static unsigned short ns9750_mii_read (unsigned short uiRegister)
672 {
673 	DEBUG_FN (DEBUG_MII_LOW);
674 
675 	/* write MII register to be read */
676 	*get_eth_reg_addr (NS9750_ETH_MADR) =
677 		NS9750_ETH_PHY_ADDRESS << 8 | uiRegister;
678 
679 	*get_eth_reg_addr (NS9750_ETH_MCMD) = NS9750_ETH_MCMD_READ;
680 
681 	if (!ns9750_mii_poll_busy ())
682 		printk (KERN_WARNING NS9750_DRIVER_NAME
683 			": MII still busy in read\n");
684 	/* continue to read */
685 
686 	*get_eth_reg_addr (NS9750_ETH_MCMD) = 0;
687 
688 	return (unsigned short) (*get_eth_reg_addr (NS9750_ETH_MRDD));
689 }
690 
691 
692 /***********************************************************************
693  * @Function: ns9750_mii_write
694  * @Return: nothing
695  * @Descr: writes the data to the PHY register. In case of a timeout,
696  *	   no special handling is performed but a message printed
697  *	   The fixed device address is being used.
698  ***********************************************************************/
699 
ns9750_mii_write(unsigned short uiRegister,unsigned short uiData)700 static void ns9750_mii_write (unsigned short uiRegister,
701 			      unsigned short uiData)
702 {
703 	DEBUG_FN (DEBUG_MII_LOW);
704 
705 	/* write MII register to be written */
706 	*get_eth_reg_addr (NS9750_ETH_MADR) =
707 		NS9750_ETH_PHY_ADDRESS << 8 | uiRegister;
708 
709 	*get_eth_reg_addr (NS9750_ETH_MWTD) = uiData;
710 
711 	if (!ns9750_mii_poll_busy ()) {
712 		printf (KERN_WARNING NS9750_DRIVER_NAME
713 			": MII still busy in write\n");
714 	}
715 }
716 
717 
718 /***********************************************************************
719  * @Function: ns9750_mii_get_clock_divisor
720  * @Return: the clock divisor that should be used in NS9750_ETH_MCFG_CLKS
721  * @Descr: if no clock divisor can be calculated for the
722  *	   current SYSCLK and the maximum MDIO Clock, a warning is printed
723  *	   and the greatest divisor is taken
724  ***********************************************************************/
725 
ns9750_mii_get_clock_divisor(unsigned int unMaxMDIOClk)726 static unsigned int ns9750_mii_get_clock_divisor (unsigned int unMaxMDIOClk)
727 {
728 	struct {
729 		unsigned int unSysClkDivisor;
730 		unsigned int unClks;	/* field for NS9750_ETH_MCFG_CLKS */
731 	} PHYClockDivisors[] = {
732 		{
733 		4, NS9750_ETH_MCFG_CLKS_4}, {
734 		6, NS9750_ETH_MCFG_CLKS_6}, {
735 		8, NS9750_ETH_MCFG_CLKS_8}, {
736 		10, NS9750_ETH_MCFG_CLKS_10}, {
737 		20, NS9750_ETH_MCFG_CLKS_20}, {
738 		30, NS9750_ETH_MCFG_CLKS_30}, {
739 		40, NS9750_ETH_MCFG_CLKS_40}
740 	};
741 
742 	int nIndexSysClkDiv;
743 	int nArraySize =
744 		sizeof (PHYClockDivisors) / sizeof (PHYClockDivisors[0]);
745 	unsigned int unClks = NS9750_ETH_MCFG_CLKS_40;	/* defaults to
746 							   greatest div */
747 
748 	DEBUG_FN (DEBUG_INIT);
749 
750 	for (nIndexSysClkDiv = 0; nIndexSysClkDiv < nArraySize;
751 	     nIndexSysClkDiv++) {
752 		/* find first sysclock divisor that isn't higher than 2.5 MHz
753 		   clock */
754 		if (AHB_CLK_FREQ /
755 		    PHYClockDivisors[nIndexSysClkDiv].unSysClkDivisor <=
756 		    unMaxMDIOClk) {
757 			unClks = PHYClockDivisors[nIndexSysClkDiv].unClks;
758 			break;
759 		}
760 	}
761 
762 	DEBUG_ARGS2 (DEBUG_INIT,
763 		     "Taking MDIO Clock bit mask 0x%0x for max clock %i\n",
764 		     unClks, unMaxMDIOClk);
765 
766 	/* return greatest divisor */
767 	return unClks;
768 }
769 
770 /***********************************************************************
771  * @Function: ns9750_mii_poll_busy
772  * @Return: 0 if timed out otherwise the remaing timeout
773  * @Descr: waits until the MII has completed a command or it times out
774  *	   code may be interrupted by hard interrupts.
775  *	   It is not checked what happens on multiple actions when
776  *	   the first is still being busy and we timeout.
777  ***********************************************************************/
778 
ns9750_mii_poll_busy(void)779 static unsigned int ns9750_mii_poll_busy (void)
780 {
781 	unsigned int unTimeout = 10000;
782 
783 	DEBUG_FN (DEBUG_MII_LOW);
784 
785 	while (((*get_eth_reg_addr (NS9750_ETH_MIND) & NS9750_ETH_MIND_BUSY)
786 		== NS9750_ETH_MIND_BUSY) && unTimeout)
787 		unTimeout--;
788 
789 	return unTimeout;
790 }
791