miiphy: convert to linux/mii.h
[platform/kernel/u-boot.git] / drivers / net / 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 /* 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
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
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
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
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
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(MII_BMCR, BMCR_RESET);
403         ns9750_mii_write(MII_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
452 static void ns9750_link_force (void)
453 {
454         unsigned short uiControl;
455
456         DEBUG_FN (DEBUG_LINK);
457
458         uiControl = ns9750_mii_read(MII_BMCR);
459         uiControl &= ~(BMCR_SPEED1000 | BMCR_SPEED100 |
460                        BMCR_ANENABLE | BMCR_FULLDPLX);
461
462         uiLastLinkStatus = 0;
463
464         if ((ucLinkMode & FS_EEPROM_AUTONEG_SPEED_MASK) ==
465             FS_EEPROM_AUTONEG_SPEED_100) {
466                 uiControl |= BMCR_SPEED100;
467                 uiLastLinkStatus |= PHY_LXT971_STAT2_100BTX;
468         }
469
470         if ((ucLinkMode & FS_EEPROM_AUTONEG_DUPLEX_MASK) ==
471             FS_EEPROM_AUTONEG_DUPLEX_FULL) {
472                 uiControl |= BMCR_FULLDPLX;
473                 uiLastLinkStatus |= PHY_LXT971_STAT2_DUPLEX_MODE;
474         }
475
476         ns9750_mii_write(MII_BMCR, uiControl);
477
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
488 static 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 */
497         ns9750_mii_write(MII_ADVERTISE,
498                          LPA_100FULL |
499                          LPA_100HALF |
500                          LPA_10FULL |
501                          LPA_10HALF |
502                          PHY_ANLPAR_PSB_802_3);
503         /* start auto-negotiation */
504         ns9750_mii_write(MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
505
506         /* wait for completion */
507
508         ulStartJiffies = get_ticks ();
509         while (get_ticks () < ulStartJiffies + NS9750_MII_NEG_DELAY) {
510                 uiStatus = ns9750_mii_read(MII_BMSR);
511                 if ((uiStatus &
512                      (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) ==
513                     (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) {
514                         /* 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
532 static 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
564 static void ns9750_link_print_changed (void)
565 {
566         unsigned short uiStatus;
567         unsigned short uiControl;
568
569         DEBUG_FN (DEBUG_LINK);
570
571         uiControl = ns9750_mii_read(MII_BMCR);
572
573         if ((uiControl & BMCR_ANENABLE) == BMCR_ANENABLE) {
574                 /* BMSR_LSTATUS is only set on autonegotiation */
575                 uiStatus = ns9750_mii_read(MII_BMSR);
576
577                 if (!(uiStatus & BMSR_LSTATUS)) {
578                         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                         }
591                         /* other PHYs must store their link information in
592                            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
627 static 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
636         phyDetected = (PhyType) uiID1 = ns9750_mii_read(MII_PHYSID1);
637
638         switch (phyDetected) {
639         case PHY_LXT971A:
640                 szName = "LXT971A";
641                 uiID2 = ns9750_mii_read(MII_PHYSID2);
642                 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
670 static 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
699 static 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
725 static 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
778 static 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 }