]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/ns9750_eth.c
rename CFG_ macros to CONFIG_SYS
[karo-tx-uboot.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(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
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
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
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
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
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
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
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
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
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 }