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