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