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