Merge branch 'origin'
[platform/kernel/u-boot.git] / drivers / tsec.c
1 /*
2  * tsec.c
3  * Freescale Three Speed Ethernet Controller driver
4  *
5  * This software may be used and distributed according to the
6  * terms of the GNU Public License, Version 2, incorporated
7  * herein by reference.
8  *
9  * Copyright 2004 Freescale Semiconductor.
10  * (C) Copyright 2003, Motorola, Inc.
11  * author Andy Fleming
12  *
13  */
14
15 #include <config.h>
16 #include <mpc85xx.h>
17 #include <common.h>
18 #include <malloc.h>
19 #include <net.h>
20 #include <command.h>
21
22 #if defined(CONFIG_TSEC_ENET)
23 #include "tsec.h"
24 #include "miiphy.h"
25
26 #define TX_BUF_CNT              2
27
28 static uint rxIdx;      /* index of the current RX buffer */
29 static uint txIdx;      /* index of the current TX buffer */
30
31 typedef volatile struct rtxbd {
32         txbd8_t txbd[TX_BUF_CNT];
33         rxbd8_t rxbd[PKTBUFSRX];
34 }  RTXBD;
35
36 struct tsec_info_struct {
37         unsigned int phyaddr;
38         u32 flags;
39         unsigned int phyregidx;
40 };
41
42
43 /* The tsec_info structure contains 3 values which the
44  * driver uses to determine how to operate a given ethernet
45  * device.  For now, the structure is initialized with the
46  * knowledge that all current implementations have 2 TSEC
47  * devices, and one FEC.  The information needed is:
48  *  phyaddr - The address of the PHY which is attached to
49  *      the given device.
50  *
51  *  flags - This variable indicates whether the device
52  *      supports gigabit speed ethernet, and whether it should be
53  *      in reduced mode.
54  *
55  *  phyregidx - This variable specifies which ethernet device
56  *      controls the MII Management registers which are connected
57  *      to the PHY.  For 8540/8560, only TSEC1 (index 0) has
58  *      access to the PHYs, so all of the entries have "0".
59  *
60  * The values specified in the table are taken from the board's
61  * config file in include/configs/.  When implementing a new
62  * board with ethernet capability, it is necessary to define:
63  *   TSEC1_PHY_ADDR
64  *   TSEC1_PHYIDX
65  *   TSEC2_PHY_ADDR
66  *   TSEC2_PHYIDX
67  *
68  * and for 8560:
69  *   FEC_PHY_ADDR
70  *   FEC_PHYIDX
71  */
72 static struct tsec_info_struct tsec_info[] = {
73 #if defined(CONFIG_MPC85XX_TSEC1) || defined(CONFIG_MPC83XX_TSEC1)
74         {TSEC1_PHY_ADDR, TSEC_GIGABIT, TSEC1_PHYIDX},
75 #else
76         { 0, 0, 0},
77 #endif
78 #if defined(CONFIG_MPC85XX_TSEC2) || defined(CONFIG_MPC83XX_TSEC2)
79         {TSEC2_PHY_ADDR, TSEC_GIGABIT, TSEC2_PHYIDX},
80 #else
81         { 0, 0, 0},
82 #endif
83 #ifdef CONFIG_MPC85XX_FEC
84         {FEC_PHY_ADDR, 0, FEC_PHYIDX},
85 #else
86 #    if defined(CONFIG_MPC85XX_TSEC3) || defined(CONFIG_MPC83XX_TSEC3)
87         {TSEC3_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC3_PHYIDX},
88 #    else
89         { 0, 0, 0},
90 #    endif
91 #    if defined(CONFIG_MPC85XX_TSEC4) || defined(CONFIG_MPC83XX_TSEC4)
92         {TSEC4_PHY_ADDR, TSEC_REDUCED, TSEC4_PHYIDX},
93 #    else
94         { 0, 0, 0},
95 #    endif
96 #endif
97 };
98
99 #define MAXCONTROLLERS  (4)
100
101 static int relocated = 0;
102
103 static struct tsec_private *privlist[MAXCONTROLLERS];
104
105 #ifdef __GNUC__
106 static RTXBD rtx __attribute__ ((aligned(8)));
107 #else
108 #error "rtx must be 64-bit aligned"
109 #endif
110
111 static int tsec_send(struct eth_device* dev, volatile void *packet, int length);
112 static int tsec_recv(struct eth_device* dev);
113 static int tsec_init(struct eth_device* dev, bd_t * bd);
114 static void tsec_halt(struct eth_device* dev);
115 static void init_registers(volatile tsec_t *regs);
116 static void startup_tsec(struct eth_device *dev);
117 static int init_phy(struct eth_device *dev);
118 void write_phy_reg(struct tsec_private *priv, uint regnum, uint value);
119 uint read_phy_reg(struct tsec_private *priv, uint regnum);
120 struct phy_info * get_phy_info(struct eth_device *dev);
121 void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);
122 static void adjust_link(struct eth_device *dev);
123 static void relocate_cmds(void);
124 static int tsec_miiphy_write(char *devname, unsigned char addr,
125                 unsigned char reg, unsigned short value);
126 static int tsec_miiphy_read(char *devname, unsigned char addr,
127                 unsigned char reg, unsigned short *value);
128
129 /* Initialize device structure. Returns success if PHY
130  * initialization succeeded (i.e. if it recognizes the PHY)
131  */
132 int tsec_initialize(bd_t *bis, int index, char *devname)
133 {
134         struct eth_device* dev;
135         int i;
136         struct tsec_private *priv;
137
138         dev = (struct eth_device*) malloc(sizeof *dev);
139
140         if(NULL == dev)
141                 return 0;
142
143         memset(dev, 0, sizeof *dev);
144
145         priv = (struct tsec_private *) malloc(sizeof(*priv));
146
147         if(NULL == priv)
148                 return 0;
149
150         privlist[index] = priv;
151         priv->regs = (volatile tsec_t *)(TSEC_BASE_ADDR + index*TSEC_SIZE);
152         priv->phyregs = (volatile tsec_t *)(TSEC_BASE_ADDR +
153                         tsec_info[index].phyregidx*TSEC_SIZE);
154
155         priv->phyaddr = tsec_info[index].phyaddr;
156         priv->flags = tsec_info[index].flags;
157
158         sprintf(dev->name, devname);
159         dev->iobase = 0;
160         dev->priv   = priv;
161         dev->init   = tsec_init;
162         dev->halt   = tsec_halt;
163         dev->send   = tsec_send;
164         dev->recv   = tsec_recv;
165
166         /* Tell u-boot to get the addr from the env */
167         for(i=0;i<6;i++)
168                 dev->enetaddr[i] = 0;
169
170         eth_register(dev);
171
172
173         /* Reset the MAC */
174         priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
175         priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
176
177 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \
178         && !defined(BITBANGMII)
179         miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write);
180 #endif
181
182         /* Try to initialize PHY here, and return */
183         return init_phy(dev);
184 }
185
186
187 /* Initializes data structures and registers for the controller,
188  * and brings the interface up.  Returns the link status, meaning
189  * that it returns success if the link is up, failure otherwise.
190  * This allows u-boot to find the first active controller. */
191 int tsec_init(struct eth_device* dev, bd_t * bd)
192 {
193         uint tempval;
194         char tmpbuf[MAC_ADDR_LEN];
195         int i;
196         struct tsec_private *priv = (struct tsec_private *)dev->priv;
197         volatile tsec_t *regs = priv->regs;
198
199         /* Make sure the controller is stopped */
200         tsec_halt(dev);
201
202         /* Init MACCFG2.  Defaults to GMII */
203         regs->maccfg2 = MACCFG2_INIT_SETTINGS;
204
205         /* Init ECNTRL */
206         regs->ecntrl = ECNTRL_INIT_SETTINGS;
207
208         /* Copy the station address into the address registers.
209          * Backwards, because little endian MACS are dumb */
210         for(i=0;i<MAC_ADDR_LEN;i++) {
211                 tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
212         }
213         regs->macstnaddr1 = *((uint *)(tmpbuf));
214
215         tempval = *((uint *)(tmpbuf +4));
216
217         regs->macstnaddr2 = tempval;
218
219         /* reset the indices to zero */
220         rxIdx = 0;
221         txIdx = 0;
222
223         /* Clear out (for the most part) the other registers */
224         init_registers(regs);
225
226         /* Ready the device for tx/rx */
227         startup_tsec(dev);
228
229         /* If there's no link, fail */
230         return priv->link;
231
232 }
233
234
235 /* Write value to the device's PHY through the registers
236  * specified in priv, modifying the register specified in regnum.
237  * It will wait for the write to be done (or for a timeout to
238  * expire) before exiting
239  */
240 void write_phy_reg(struct tsec_private *priv, uint regnum, uint value)
241 {
242         volatile tsec_t *regbase = priv->phyregs;
243         uint phyid = priv->phyaddr;
244         int timeout=1000000;
245
246         regbase->miimadd = (phyid << 8) | regnum;
247         regbase->miimcon = value;
248         asm("sync");
249
250         timeout=1000000;
251         while((regbase->miimind & MIIMIND_BUSY) && timeout--);
252 }
253
254
255 /* Reads register regnum on the device's PHY through the
256  * registers specified in priv.  It lowers and raises the read
257  * command, and waits for the data to become valid (miimind
258  * notvalid bit cleared), and the bus to cease activity (miimind
259  * busy bit cleared), and then returns the value
260  */
261 uint read_phy_reg(struct tsec_private *priv, uint regnum)
262 {
263         uint value;
264         volatile tsec_t *regbase = priv->phyregs;
265         uint phyid = priv->phyaddr;
266
267         /* Put the address of the phy, and the register
268          * number into MIIMADD */
269         regbase->miimadd = (phyid << 8) | regnum;
270
271         /* Clear the command register, and wait */
272         regbase->miimcom = 0;
273         asm("sync");
274
275         /* Initiate a read command, and wait */
276         regbase->miimcom = MIIM_READ_COMMAND;
277         asm("sync");
278
279         /* Wait for the the indication that the read is done */
280         while((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY)));
281
282         /* Grab the value read from the PHY */
283         value = regbase->miimstat;
284
285         return value;
286 }
287
288
289 /* Discover which PHY is attached to the device, and configure it
290  * properly.  If the PHY is not recognized, then return 0
291  * (failure).  Otherwise, return 1
292  */
293 static int init_phy(struct eth_device *dev)
294 {
295         struct tsec_private *priv = (struct tsec_private *)dev->priv;
296         struct phy_info *curphy;
297
298         /* Assign a Physical address to the TBI */
299
300         {
301                 volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);
302                 regs->tbipa = TBIPA_VALUE;
303                 regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE);
304                 regs->tbipa = TBIPA_VALUE;
305                 asm("sync");
306         }
307
308         /* Reset MII (due to new addresses) */
309         priv->phyregs->miimcfg = MIIMCFG_RESET;
310         asm("sync");
311         priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE;
312         asm("sync");
313         while(priv->phyregs->miimind & MIIMIND_BUSY);
314
315         if(0 == relocated)
316                 relocate_cmds();
317
318         /* Get the cmd structure corresponding to the attached
319          * PHY */
320         curphy = get_phy_info(dev);
321
322         if(NULL == curphy) {
323                 printf("%s: No PHY found\n", dev->name);
324
325                 return 0;
326         }
327
328         priv->phyinfo = curphy;
329
330         phy_run_commands(priv, priv->phyinfo->config);
331
332         return 1;
333 }
334
335
336 /* Returns which value to write to the control register. */
337 /* For 10/100, the value is slightly different */
338 uint mii_cr_init(uint mii_reg, struct tsec_private *priv)
339 {
340         if(priv->flags & TSEC_GIGABIT)
341                 return MIIM_CONTROL_INIT;
342         else
343                 return MIIM_CR_INIT;
344 }
345
346
347 /* Parse the status register for link, and then do
348  * auto-negotiation */
349 uint mii_parse_sr(uint mii_reg, struct tsec_private *priv)
350 {
351         /*
352          * Wait if PHY is capable of autonegotiation and autonegotiation is not complete
353          */
354         mii_reg = read_phy_reg(priv, MIIM_STATUS);
355         if ((mii_reg & PHY_BMSR_AUTN_ABLE) && !(mii_reg & PHY_BMSR_AUTN_COMP)) {
356                 int i = 0;
357
358                 puts ("Waiting for PHY auto negotiation to complete");
359                 while (!((mii_reg & PHY_BMSR_AUTN_COMP) && (mii_reg & MIIM_STATUS_LINK))) {
360                         /*
361                          * Timeout reached ?
362                          */
363                         if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
364                                 puts (" TIMEOUT !\n");
365                                 priv->link = 0;
366                                 break;
367                         }
368
369                         if ((i++ % 1000) == 0) {
370                                 putc ('.');
371                         }
372                         udelay (1000);  /* 1 ms */
373                         mii_reg = read_phy_reg(priv, MIIM_STATUS);
374                 }
375                 puts (" done\n");
376                 priv->link = 1;
377                 udelay (500000);        /* another 500 ms (results in faster booting) */
378         } else {
379                 priv->link = 1;
380         }
381
382         return 0;
383 }
384
385
386 /* Parse the 88E1011's status register for speed and duplex
387  * information */
388 uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private *priv)
389 {
390         uint speed;
391
392         mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
393
394         if (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
395               (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
396                 int i = 0;
397
398                 puts ("Waiting for PHY realtime link");
399                 while (!((mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE) &&
400                          (mii_reg & MIIM_88E1011_PHYSTAT_LINK))) {
401                         /*
402                          * Timeout reached ?
403                          */
404                         if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
405                                 puts (" TIMEOUT !\n");
406                                 priv->link = 0;
407                                 break;
408                         }
409
410                         if ((i++ % 1000) == 0) {
411                                 putc ('.');
412                         }
413                         udelay (1000);  /* 1 ms */
414                         mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
415                 }
416                 puts (" done\n");
417                 udelay (500000);        /* another 500 ms (results in faster booting) */
418         }
419
420         if(mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
421                 priv->duplexity = 1;
422         else
423                 priv->duplexity = 0;
424
425         speed = (mii_reg &MIIM_88E1011_PHYSTAT_SPEED);
426
427         switch(speed) {
428                 case MIIM_88E1011_PHYSTAT_GBIT:
429                         priv->speed = 1000;
430                         break;
431                 case MIIM_88E1011_PHYSTAT_100:
432                         priv->speed = 100;
433                         break;
434                 default:
435                         priv->speed = 10;
436         }
437
438         return 0;
439 }
440
441
442 /* Parse the cis8201's status register for speed and duplex
443  * information */
444 uint mii_parse_cis8201(uint mii_reg, struct tsec_private *priv)
445 {
446         uint speed;
447
448         if(mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
449                 priv->duplexity = 1;
450         else
451                 priv->duplexity = 0;
452
453         speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
454         switch(speed) {
455                 case MIIM_CIS8201_AUXCONSTAT_GBIT:
456                         priv->speed = 1000;
457                         break;
458                 case MIIM_CIS8201_AUXCONSTAT_100:
459                         priv->speed = 100;
460                         break;
461                 default:
462                         priv->speed = 10;
463                         break;
464         }
465
466         return 0;
467 }
468
469
470 /* Parse the DM9161's status register for speed and duplex
471  * information */
472 uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private *priv)
473 {
474         if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
475                 priv->speed = 100;
476         else
477                 priv->speed = 10;
478
479         if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
480                 priv->duplexity = 1;
481         else
482                 priv->duplexity = 0;
483
484         return 0;
485 }
486
487
488 /* Hack to write all 4 PHYs with the LED values */
489 uint mii_cis8204_fixled(uint mii_reg, struct tsec_private *priv)
490 {
491         uint phyid;
492         volatile tsec_t *regbase = priv->phyregs;
493         int timeout=1000000;
494
495         for(phyid=0;phyid<4;phyid++) {
496                 regbase->miimadd = (phyid << 8) | mii_reg;
497                 regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT;
498                 asm("sync");
499
500                 timeout=1000000;
501                 while((regbase->miimind & MIIMIND_BUSY) && timeout--);
502         }
503
504         return MIIM_CIS8204_SLEDCON_INIT;
505 }
506
507 uint mii_cis8204_setmode(uint mii_reg, struct tsec_private *priv)
508 {
509         if (priv->flags & TSEC_REDUCED)
510                 return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII;
511         else
512                 return MIIM_CIS8204_EPHYCON_INIT;
513 }
514
515 /* Initialized required registers to appropriate values, zeroing
516  * those we don't care about (unless zero is bad, in which case,
517  * choose a more appropriate value) */
518 static void init_registers(volatile tsec_t *regs)
519 {
520         /* Clear IEVENT */
521         regs->ievent = IEVENT_INIT_CLEAR;
522
523         regs->imask = IMASK_INIT_CLEAR;
524
525         regs->hash.iaddr0 = 0;
526         regs->hash.iaddr1 = 0;
527         regs->hash.iaddr2 = 0;
528         regs->hash.iaddr3 = 0;
529         regs->hash.iaddr4 = 0;
530         regs->hash.iaddr5 = 0;
531         regs->hash.iaddr6 = 0;
532         regs->hash.iaddr7 = 0;
533
534         regs->hash.gaddr0 = 0;
535         regs->hash.gaddr1 = 0;
536         regs->hash.gaddr2 = 0;
537         regs->hash.gaddr3 = 0;
538         regs->hash.gaddr4 = 0;
539         regs->hash.gaddr5 = 0;
540         regs->hash.gaddr6 = 0;
541         regs->hash.gaddr7 = 0;
542
543         regs->rctrl = 0x00000000;
544
545         /* Init RMON mib registers */
546         memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
547
548         regs->rmon.cam1 = 0xffffffff;
549         regs->rmon.cam2 = 0xffffffff;
550
551         regs->mrblr = MRBLR_INIT_SETTINGS;
552
553         regs->minflr = MINFLR_INIT_SETTINGS;
554
555         regs->attr = ATTR_INIT_SETTINGS;
556         regs->attreli = ATTRELI_INIT_SETTINGS;
557
558 }
559
560
561 /* Configure maccfg2 based on negotiated speed and duplex
562  * reported by PHY handling code */
563 static void adjust_link(struct eth_device *dev)
564 {
565         struct tsec_private *priv = (struct tsec_private *)dev->priv;
566         volatile tsec_t *regs = priv->regs;
567
568         if(priv->link) {
569                 if(priv->duplexity != 0)
570                         regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
571                 else
572                         regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX);
573
574                 switch(priv->speed) {
575                         case 1000:
576                                 regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
577                                         | MACCFG2_GMII);
578                                 break;
579                         case 100:
580                         case 10:
581                                 regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
582                                         | MACCFG2_MII);
583
584                                 /* If We're in reduced mode, we need
585                                  * to say whether we're 10 or 100 MB.
586                                  */
587                                 if ((priv->speed == 100)
588                                     && (priv->flags & TSEC_REDUCED))
589                                         regs->ecntrl |= ECNTRL_R100;
590                                 else
591                                         regs->ecntrl &= ~(ECNTRL_R100);
592                                 break;
593                         default:
594                                 printf("%s: Speed was bad\n", dev->name);
595                                 break;
596                 }
597
598                 printf("Speed: %d, %s duplex\n", priv->speed,
599                                 (priv->duplexity) ? "full" : "half");
600
601         } else {
602                 printf("%s: No link.\n", dev->name);
603         }
604 }
605
606
607 /* Set up the buffers and their descriptors, and bring up the
608  * interface */
609 static void startup_tsec(struct eth_device *dev)
610 {
611         int i;
612         struct tsec_private *priv = (struct tsec_private *)dev->priv;
613         volatile tsec_t *regs = priv->regs;
614
615         /* Point to the buffer descriptors */
616         regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
617         regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
618
619         /* Initialize the Rx Buffer descriptors */
620         for (i = 0; i < PKTBUFSRX; i++) {
621                 rtx.rxbd[i].status = RXBD_EMPTY;
622                 rtx.rxbd[i].length = 0;
623                 rtx.rxbd[i].bufPtr = (uint)NetRxPackets[i];
624         }
625         rtx.rxbd[PKTBUFSRX -1].status |= RXBD_WRAP;
626
627         /* Initialize the TX Buffer Descriptors */
628         for(i=0; i<TX_BUF_CNT; i++) {
629                 rtx.txbd[i].status = 0;
630                 rtx.txbd[i].length = 0;
631                 rtx.txbd[i].bufPtr = 0;
632         }
633         rtx.txbd[TX_BUF_CNT -1].status |= TXBD_WRAP;
634
635         /* Start up the PHY */
636         phy_run_commands(priv, priv->phyinfo->startup);
637         adjust_link(dev);
638
639         /* Enable Transmit and Receive */
640         regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
641
642         /* Tell the DMA it is clear to go */
643         regs->dmactrl |= DMACTRL_INIT_SETTINGS;
644         regs->tstat = TSTAT_CLEAR_THALT;
645         regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
646 }
647
648 /* This returns the status bits of the device.  The return value
649  * is never checked, and this is what the 8260 driver did, so we
650  * do the same.  Presumably, this would be zero if there were no
651  * errors */
652 static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
653 {
654         int i;
655         int result = 0;
656         struct tsec_private *priv = (struct tsec_private *)dev->priv;
657         volatile tsec_t *regs = priv->regs;
658
659         /* Find an empty buffer descriptor */
660         for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
661                 if (i >= TOUT_LOOP) {
662                         debug ("%s: tsec: tx buffers full\n", dev->name);
663                         return result;
664                 }
665         }
666
667         rtx.txbd[txIdx].bufPtr = (uint)packet;
668         rtx.txbd[txIdx].length = length;
669         rtx.txbd[txIdx].status |= (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
670
671         /* Tell the DMA to go */
672         regs->tstat = TSTAT_CLEAR_THALT;
673
674         /* Wait for buffer to be transmitted */
675         for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
676                 if (i >= TOUT_LOOP) {
677                         debug ("%s: tsec: tx error\n", dev->name);
678                         return result;
679                 }
680         }
681
682         txIdx = (txIdx + 1) % TX_BUF_CNT;
683         result = rtx.txbd[txIdx].status & TXBD_STATS;
684
685         return result;
686 }
687
688 static int tsec_recv(struct eth_device* dev)
689 {
690         int length;
691         struct tsec_private *priv = (struct tsec_private *)dev->priv;
692         volatile tsec_t *regs = priv->regs;
693
694         while(!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
695
696                 length = rtx.rxbd[rxIdx].length;
697
698                 /* Send the packet up if there were no errors */
699                 if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
700                         NetReceive(NetRxPackets[rxIdx], length - 4);
701                 } else {
702                         printf("Got error %x\n",
703                                         (rtx.rxbd[rxIdx].status & RXBD_STATS));
704                 }
705
706                 rtx.rxbd[rxIdx].length = 0;
707
708                 /* Set the wrap bit if this is the last element in the list */
709                 rtx.rxbd[rxIdx].status = RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
710
711                 rxIdx = (rxIdx + 1) % PKTBUFSRX;
712         }
713
714         if(regs->ievent&IEVENT_BSY) {
715                 regs->ievent = IEVENT_BSY;
716                 regs->rstat = RSTAT_CLEAR_RHALT;
717         }
718
719         return -1;
720
721 }
722
723
724 /* Stop the interface */
725 static void tsec_halt(struct eth_device* dev)
726 {
727         struct tsec_private *priv = (struct tsec_private *)dev->priv;
728         volatile tsec_t *regs = priv->regs;
729
730         regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
731         regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
732
733         while(!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)));
734
735         regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
736
737         /* Shut down the PHY, as needed */
738         phy_run_commands(priv, priv->phyinfo->shutdown);
739 }
740
741
742 struct phy_info phy_info_M88E1011S = {
743         0x01410c6,
744         "Marvell 88E1011S",
745         4,
746         (struct phy_cmd[]) { /* config */
747                 /* Reset and configure the PHY */
748                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
749                 {0x1d, 0x1f, NULL},
750                 {0x1e, 0x200c, NULL},
751                 {0x1d, 0x5, NULL},
752                 {0x1e, 0x0, NULL},
753                 {0x1e, 0x100, NULL},
754                 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
755                 {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
756                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
757                 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
758                 {miim_end,}
759         },
760         (struct phy_cmd[]) { /* startup */
761                 /* Status is read once to clear old link state */
762                 {MIIM_STATUS, miim_read, NULL},
763                 /* Auto-negotiate */
764                 {MIIM_STATUS, miim_read, &mii_parse_sr},
765                 /* Read the status */
766                 {MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
767                 {miim_end,}
768         },
769         (struct phy_cmd[]) { /* shutdown */
770                 {miim_end,}
771         },
772 };
773
774 struct phy_info phy_info_M88E1111S = {
775         0x01410cc,
776         "Marvell 88E1111S",
777         4,
778         (struct phy_cmd[]) { /* config */
779           /* Reset and configure the PHY */
780                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
781                 {0x1d, 0x1f, NULL},
782                 {0x1e, 0x200c, NULL},
783                 {0x1d, 0x5, NULL},
784                 {0x1e, 0x0, NULL},
785                 {0x1e, 0x100, NULL},
786                 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
787                 {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
788                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
789                 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
790                 {miim_end,}
791         },
792         (struct phy_cmd[]) { /* startup */
793           /* Status is read once to clear old link state */
794                 {MIIM_STATUS, miim_read, NULL},
795                 /* Auto-negotiate */
796                 {MIIM_STATUS, miim_read, &mii_parse_sr},
797                 /* Read the status */
798                 {MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
799                 {miim_end,}
800         },
801         (struct phy_cmd[]) { /* shutdown */
802                 {miim_end,}
803         },
804 };
805
806 struct phy_info phy_info_cis8204 = {
807         0x3f11,
808         "Cicada Cis8204",
809         6,
810         (struct phy_cmd[]) { /* config */
811                 /* Override PHY config settings */
812                 {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
813                 /* Configure some basic stuff */
814                 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
815                 {MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT, &mii_cis8204_fixled},
816                 {MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT, &mii_cis8204_setmode},
817                 {miim_end,}
818         },
819         (struct phy_cmd[]) { /* startup */
820                 /* Read the Status (2x to make sure link is right) */
821                 {MIIM_STATUS, miim_read, NULL},
822                 /* Auto-negotiate */
823                 {MIIM_STATUS, miim_read, &mii_parse_sr},
824                 /* Read the status */
825                 {MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
826                 {miim_end,}
827         },
828         (struct phy_cmd[]) { /* shutdown */
829                 {miim_end,}
830         },
831 };
832
833 /* Cicada 8201 */
834 struct phy_info phy_info_cis8201 = {
835         0xfc41,
836         "CIS8201",
837         4,
838         (struct phy_cmd[]) { /* config */
839                 /* Override PHY config settings */
840                 {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
841                 /* Set up the interface mode */
842                 {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
843                 /* Configure some basic stuff */
844                 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
845                 {miim_end,}
846         },
847         (struct phy_cmd[]) { /* startup */
848                 /* Read the Status (2x to make sure link is right) */
849                 {MIIM_STATUS, miim_read, NULL},
850                 /* Auto-negotiate */
851                 {MIIM_STATUS, miim_read, &mii_parse_sr},
852                 /* Read the status */
853                 {MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
854                 {miim_end,}
855         },
856         (struct phy_cmd[]) { /* shutdown */
857                 {miim_end,}
858         },
859 };
860
861
862 struct phy_info phy_info_dm9161 = {
863         0x0181b88,
864         "Davicom DM9161E",
865         4,
866         (struct phy_cmd[]) { /* config */
867                 {MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL},
868                 /* Do not bypass the scrambler/descrambler */
869                 {MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL},
870                 /* Clear 10BTCSR to default */
871                 {MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, NULL},
872                 /* Configure some basic stuff */
873                 {MIIM_CONTROL, MIIM_CR_INIT, NULL},
874                 /* Restart Auto Negotiation */
875                 {MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL},
876                 {miim_end,}
877         },
878         (struct phy_cmd[]) { /* startup */
879                 /* Status is read once to clear old link state */
880                 {MIIM_STATUS, miim_read, NULL},
881                 /* Auto-negotiate */
882                 {MIIM_STATUS, miim_read, &mii_parse_sr},
883                 /* Read the status */
884                 {MIIM_DM9161_SCSR, miim_read, &mii_parse_dm9161_scsr},
885                 {miim_end,}
886         },
887         (struct phy_cmd[]) { /* shutdown */
888                 {miim_end,}
889         },
890 };
891
892 uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
893 {
894         unsigned int speed;
895         if (priv->link) {
896                 speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
897
898                 switch (speed) {
899                 case MIIM_LXT971_SR2_10HDX:
900                         priv->speed = 10;
901                         priv->duplexity = 0;
902                         break;
903                 case MIIM_LXT971_SR2_10FDX:
904                         priv->speed = 10;
905                         priv->duplexity = 1;
906                         break;
907                 case MIIM_LXT971_SR2_100HDX:
908                         priv->speed = 100;
909                         priv->duplexity = 0;
910                 default:
911                         priv->speed = 100;
912                         priv->duplexity = 1;
913                         break;
914                 }
915         } else {
916                 priv->speed = 0;
917                 priv->duplexity = 0;
918         }
919
920         return 0;
921 }
922
923 static struct phy_info phy_info_lxt971 = {
924         0x0001378e,
925         "LXT971",
926         4,
927         (struct phy_cmd []) {  /* config */
928                 { MIIM_CR, MIIM_CR_INIT, mii_cr_init }, /* autonegotiate */
929                 { miim_end, }
930         },
931         (struct phy_cmd []) {  /* startup - enable interrupts */
932                 /* { 0x12, 0x00f2, NULL }, */
933                 { MIIM_STATUS, miim_read, NULL },
934                 { MIIM_STATUS, miim_read, &mii_parse_sr },
935                 { MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2 },
936                 { miim_end, }
937         },
938         (struct phy_cmd []) {  /* shutdown - disable interrupts */
939                 { miim_end, }
940         },
941 };
942
943 /* Parse the DP83865's link and auto-neg status register for speed and duplex
944  * information */
945 uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv)
946 {
947         switch (mii_reg & MIIM_DP83865_SPD_MASK) {
948
949         case MIIM_DP83865_SPD_1000:
950                 priv->speed = 1000;
951                 break;
952
953         case MIIM_DP83865_SPD_100:
954                 priv->speed = 100;
955                 break;
956
957         default:
958                 priv->speed = 10;
959                 break;
960
961         }
962
963         if (mii_reg & MIIM_DP83865_DPX_FULL)
964                 priv->duplexity = 1;
965         else
966                 priv->duplexity = 0;
967
968         return 0;
969 }
970
971 struct phy_info phy_info_dp83865 = {
972         0x20005c7,
973         "NatSemi DP83865",
974         4,
975         (struct phy_cmd[]) { /* config */
976                 {MIIM_CONTROL, MIIM_DP83865_CR_INIT, NULL},
977                 {miim_end,}
978         },
979         (struct phy_cmd[]) { /* startup */
980                 /* Status is read once to clear old link state */
981                 {MIIM_STATUS, miim_read, NULL},
982                 /* Auto-negotiate */
983                 {MIIM_STATUS, miim_read, &mii_parse_sr},
984                 /* Read the link and auto-neg status */
985                 {MIIM_DP83865_LANR, miim_read, &mii_parse_dp83865_lanr},
986                 {miim_end,}
987         },
988         (struct phy_cmd[]) { /* shutdown */
989                 {miim_end,}
990         },
991 };
992
993 struct phy_info *phy_info[] = {
994 #if 0
995         &phy_info_cis8201,
996 #endif
997         &phy_info_cis8204,
998         &phy_info_M88E1011S,
999         &phy_info_M88E1111S,
1000         &phy_info_dm9161,
1001         &phy_info_lxt971,
1002         &phy_info_dp83865,
1003         NULL
1004 };
1005
1006
1007 /* Grab the identifier of the device's PHY, and search through
1008  * all of the known PHYs to see if one matches.  If so, return
1009  * it, if not, return NULL */
1010 struct phy_info * get_phy_info(struct eth_device *dev)
1011 {
1012         struct tsec_private *priv = (struct tsec_private *)dev->priv;
1013         uint phy_reg, phy_ID;
1014         int i;
1015         struct phy_info *theInfo = NULL;
1016
1017         /* Grab the bits from PHYIR1, and put them in the upper half */
1018         phy_reg = read_phy_reg(priv, MIIM_PHYIR1);
1019         phy_ID = (phy_reg & 0xffff) << 16;
1020
1021         /* Grab the bits from PHYIR2, and put them in the lower half */
1022         phy_reg = read_phy_reg(priv, MIIM_PHYIR2);
1023         phy_ID |= (phy_reg & 0xffff);
1024
1025         /* loop through all the known PHY types, and find one that */
1026         /* matches the ID we read from the PHY. */
1027         for(i=0; phy_info[i]; i++) {
1028                 if(phy_info[i]->id == (phy_ID >> phy_info[i]->shift))
1029                         theInfo = phy_info[i];
1030         }
1031
1032         if(theInfo == NULL)
1033         {
1034                 printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
1035                 return NULL;
1036         } else {
1037                 debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID);
1038         }
1039
1040         return theInfo;
1041 }
1042
1043
1044 /* Execute the given series of commands on the given device's
1045  * PHY, running functions as necessary*/
1046 void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
1047 {
1048         int i;
1049         uint result;
1050         volatile tsec_t *phyregs = priv->phyregs;
1051
1052         phyregs->miimcfg = MIIMCFG_RESET;
1053
1054         phyregs->miimcfg = MIIMCFG_INIT_VALUE;
1055
1056         while(phyregs->miimind & MIIMIND_BUSY);
1057
1058         for(i=0;cmd->mii_reg != miim_end;i++) {
1059                 if(cmd->mii_data == miim_read) {
1060                         result = read_phy_reg(priv, cmd->mii_reg);
1061
1062                         if(cmd->funct != NULL)
1063                                 (*(cmd->funct))(result, priv);
1064
1065                 } else {
1066                         if(cmd->funct != NULL)
1067                                 result = (*(cmd->funct))(cmd->mii_reg, priv);
1068                         else
1069                                 result = cmd->mii_data;
1070
1071                         write_phy_reg(priv, cmd->mii_reg, result);
1072
1073                 }
1074                 cmd++;
1075         }
1076 }
1077
1078
1079 /* Relocate the function pointers in the phy cmd lists */
1080 static void relocate_cmds(void)
1081 {
1082         struct phy_cmd **cmdlistptr;
1083         struct phy_cmd *cmd;
1084         int i,j,k;
1085         DECLARE_GLOBAL_DATA_PTR;
1086
1087         for(i=0; phy_info[i]; i++) {
1088                 /* First thing's first: relocate the pointers to the
1089                  * PHY command structures (the structs were done) */
1090                 phy_info[i] = (struct phy_info *) ((uint)phy_info[i]
1091                                 + gd->reloc_off);
1092                 phy_info[i]->name += gd->reloc_off;
1093                 phy_info[i]->config =
1094                         (struct phy_cmd *)((uint)phy_info[i]->config
1095                                            + gd->reloc_off);
1096                 phy_info[i]->startup =
1097                         (struct phy_cmd *)((uint)phy_info[i]->startup
1098                                            + gd->reloc_off);
1099                 phy_info[i]->shutdown =
1100                         (struct phy_cmd *)((uint)phy_info[i]->shutdown
1101                                            + gd->reloc_off);
1102
1103                 cmdlistptr = &phy_info[i]->config;
1104                 j=0;
1105                 for(;cmdlistptr <= &phy_info[i]->shutdown;cmdlistptr++) {
1106                         k=0;
1107                         for(cmd=*cmdlistptr;cmd->mii_reg != miim_end;cmd++) {
1108                                 /* Only relocate non-NULL pointers */
1109                                 if(cmd->funct)
1110                                         cmd->funct += gd->reloc_off;
1111
1112                                 k++;
1113                         }
1114                         j++;
1115                 }
1116         }
1117
1118         relocated = 1;
1119 }
1120
1121
1122 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \
1123         && !defined(BITBANGMII)
1124
1125 struct tsec_private * get_priv_for_phy(unsigned char phyaddr)
1126 {
1127         int i;
1128
1129         for(i=0;i<MAXCONTROLLERS;i++) {
1130                 if(privlist[i]->phyaddr == phyaddr)
1131                         return privlist[i];
1132         }
1133
1134         return NULL;
1135 }
1136
1137 /*
1138  * Read a MII PHY register.
1139  *
1140  * Returns:
1141  *  0 on success
1142  */
1143 static int tsec_miiphy_read(char *devname, unsigned char addr,
1144                 unsigned char reg, unsigned short *value)
1145 {
1146         unsigned short ret;
1147         struct tsec_private *priv = get_priv_for_phy(addr);
1148
1149         if(NULL == priv) {
1150                 printf("Can't read PHY at address %d\n", addr);
1151                 return -1;
1152         }
1153
1154         ret = (unsigned short)read_phy_reg(priv, reg);
1155         *value = ret;
1156
1157         return 0;
1158 }
1159
1160 /*
1161  * Write a MII PHY register.
1162  *
1163  * Returns:
1164  *  0 on success
1165  */
1166 static int tsec_miiphy_write(char *devname, unsigned char addr,
1167                 unsigned char reg, unsigned short value)
1168 {
1169         struct tsec_private *priv = get_priv_for_phy(addr);
1170
1171         if(NULL == priv) {
1172                 printf("Can't write PHY at address %d\n", addr);
1173                 return -1;
1174         }
1175
1176         write_phy_reg(priv, reg, value);
1177
1178         return 0;
1179 }
1180
1181 #endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
1182                 && !defined(BITBANGMII) */
1183
1184 #endif /* CONFIG_TSEC_ENET */