399116f3a258c6540fe13c6f88d778847719bd83
[oweals/u-boot.git] / drivers / net / 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, 2007 Freescale Semiconductor, Inc.
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 #include <tsec.h>
20
21 #include "miiphy.h"
22
23 DECLARE_GLOBAL_DATA_PTR;
24
25 #define TX_BUF_CNT              2
26
27 static uint rxIdx;              /* index of the current RX buffer */
28 static uint txIdx;              /* index of the current TX buffer */
29
30 typedef volatile struct rtxbd {
31         txbd8_t txbd[TX_BUF_CNT];
32         rxbd8_t rxbd[PKTBUFSRX];
33 } RTXBD;
34
35 #define MAXCONTROLLERS  (8)
36
37 static int relocated = 0;
38
39 static struct tsec_private *privlist[MAXCONTROLLERS];
40 static int num_tsecs = 0;
41
42 #ifdef __GNUC__
43 static RTXBD rtx __attribute__ ((aligned(8)));
44 #else
45 #error "rtx must be 64-bit aligned"
46 #endif
47
48 static int tsec_send(struct eth_device *dev,
49                      volatile void *packet, int length);
50 static int tsec_recv(struct eth_device *dev);
51 static int tsec_init(struct eth_device *dev, bd_t * bd);
52 static void tsec_halt(struct eth_device *dev);
53 static void init_registers(volatile tsec_t * regs);
54 static void startup_tsec(struct eth_device *dev);
55 static int init_phy(struct eth_device *dev);
56 void write_phy_reg(struct tsec_private *priv, uint regnum, uint value);
57 uint read_phy_reg(struct tsec_private *priv, uint regnum);
58 struct phy_info *get_phy_info(struct eth_device *dev);
59 void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);
60 static void adjust_link(struct eth_device *dev);
61 static void relocate_cmds(void);
62 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
63         && !defined(BITBANGMII)
64 static int tsec_miiphy_write(char *devname, unsigned char addr,
65                              unsigned char reg, unsigned short value);
66 static int tsec_miiphy_read(char *devname, unsigned char addr,
67                             unsigned char reg, unsigned short *value);
68 #endif
69 #ifdef CONFIG_MCAST_TFTP
70 static int tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set);
71 #endif
72
73 /* Default initializations for TSEC controllers. */
74
75 static struct tsec_info_struct tsec_info[] = {
76 #ifdef CONFIG_TSEC1
77         STD_TSEC_INFO(1),       /* TSEC1 */
78 #endif
79 #ifdef CONFIG_TSEC2
80         STD_TSEC_INFO(2),       /* TSEC2 */
81 #endif
82 #ifdef CONFIG_MPC85XX_FEC
83         {
84                 .regs = (tsec_t *)(TSEC_BASE_ADDR + 0x2000),
85                 .miiregs = (tsec_t *)(TSEC_BASE_ADDR),
86                 .devname = CONFIG_MPC85XX_FEC_NAME,
87                 .phyaddr = FEC_PHY_ADDR,
88                 .flags = FEC_FLAGS
89         },                      /* FEC */
90 #endif
91 #ifdef CONFIG_TSEC3
92         STD_TSEC_INFO(3),       /* TSEC3 */
93 #endif
94 #ifdef CONFIG_TSEC4
95         STD_TSEC_INFO(4),       /* TSEC4 */
96 #endif
97 };
98
99 int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
100 {
101         int i;
102
103         for (i = 0; i < num; i++)
104                 tsec_initialize(bis, &tsecs[i]);
105
106         return 0;
107 }
108
109 int tsec_standard_init(bd_t *bis)
110 {
111         return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
112 }
113
114 /* Initialize device structure. Returns success if PHY
115  * initialization succeeded (i.e. if it recognizes the PHY)
116  */
117 int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info)
118 {
119         struct eth_device *dev;
120         int i;
121         struct tsec_private *priv;
122
123         dev = (struct eth_device *)malloc(sizeof *dev);
124
125         if (NULL == dev)
126                 return 0;
127
128         memset(dev, 0, sizeof *dev);
129
130         priv = (struct tsec_private *)malloc(sizeof(*priv));
131
132         if (NULL == priv)
133                 return 0;
134
135         privlist[num_tsecs++] = priv;
136         priv->regs = tsec_info->regs;
137         priv->phyregs = tsec_info->miiregs;
138
139         priv->phyaddr = tsec_info->phyaddr;
140         priv->flags = tsec_info->flags;
141
142         sprintf(dev->name, tsec_info->devname);
143         dev->iobase = 0;
144         dev->priv = priv;
145         dev->init = tsec_init;
146         dev->halt = tsec_halt;
147         dev->send = tsec_send;
148         dev->recv = tsec_recv;
149 #ifdef CONFIG_MCAST_TFTP
150         dev->mcast = tsec_mcast_addr;
151 #endif
152
153         /* Tell u-boot to get the addr from the env */
154         for (i = 0; i < 6; i++)
155                 dev->enetaddr[i] = 0;
156
157         eth_register(dev);
158
159         /* Reset the MAC */
160         priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
161         udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
162         priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
163
164 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
165         && !defined(BITBANGMII)
166         miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write);
167 #endif
168
169         /* Try to initialize PHY here, and return */
170         return init_phy(dev);
171 }
172
173 /* Initializes data structures and registers for the controller,
174  * and brings the interface up.  Returns the link status, meaning
175  * that it returns success if the link is up, failure otherwise.
176  * This allows u-boot to find the first active controller.
177  */
178 int tsec_init(struct eth_device *dev, bd_t * bd)
179 {
180         uint tempval;
181         char tmpbuf[MAC_ADDR_LEN];
182         int i;
183         struct tsec_private *priv = (struct tsec_private *)dev->priv;
184         volatile tsec_t *regs = priv->regs;
185
186         /* Make sure the controller is stopped */
187         tsec_halt(dev);
188
189         /* Init MACCFG2.  Defaults to GMII */
190         regs->maccfg2 = MACCFG2_INIT_SETTINGS;
191
192         /* Init ECNTRL */
193         regs->ecntrl = ECNTRL_INIT_SETTINGS;
194
195         /* Copy the station address into the address registers.
196          * Backwards, because little endian MACS are dumb */
197         for (i = 0; i < MAC_ADDR_LEN; i++) {
198                 tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
199         }
200         regs->macstnaddr1 = *((uint *) (tmpbuf));
201
202         tempval = *((uint *) (tmpbuf + 4));
203
204         regs->macstnaddr2 = tempval;
205
206         /* reset the indices to zero */
207         rxIdx = 0;
208         txIdx = 0;
209
210         /* Clear out (for the most part) the other registers */
211         init_registers(regs);
212
213         /* Ready the device for tx/rx */
214         startup_tsec(dev);
215
216         /* If there's no link, fail */
217         return (priv->link ? 0 : -1);
218 }
219
220 /* Writes the given phy's reg with value, using the specified MDIO regs */
221 static void tsec_local_mdio_write(volatile tsec_t *phyregs, uint addr,
222                 uint reg, uint value)
223 {
224         int timeout = 1000000;
225
226         phyregs->miimadd = (addr << 8) | reg;
227         phyregs->miimcon = value;
228         asm("sync");
229
230         timeout = 1000000;
231         while ((phyregs->miimind & MIIMIND_BUSY) && timeout--) ;
232 }
233
234
235 /* Provide the default behavior of writing the PHY of this ethernet device */
236 #define write_phy_reg(priv, regnum, value) tsec_local_mdio_write(priv->phyregs,priv->phyaddr,regnum,value)
237
238 /* Reads register regnum on the device's PHY through the
239  * specified registers.  It lowers and raises the read
240  * command, and waits for the data to become valid (miimind
241  * notvalid bit cleared), and the bus to cease activity (miimind
242  * busy bit cleared), and then returns the value
243  */
244 uint tsec_local_mdio_read(volatile tsec_t *phyregs, uint phyid, uint regnum)
245 {
246         uint value;
247
248         /* Put the address of the phy, and the register
249          * number into MIIMADD */
250         phyregs->miimadd = (phyid << 8) | regnum;
251
252         /* Clear the command register, and wait */
253         phyregs->miimcom = 0;
254         asm("sync");
255
256         /* Initiate a read command, and wait */
257         phyregs->miimcom = MIIM_READ_COMMAND;
258         asm("sync");
259
260         /* Wait for the the indication that the read is done */
261         while ((phyregs->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ;
262
263         /* Grab the value read from the PHY */
264         value = phyregs->miimstat;
265
266         return value;
267 }
268
269 /* #define to provide old read_phy_reg functionality without duplicating code */
270 #define read_phy_reg(priv,regnum) tsec_local_mdio_read(priv->phyregs,priv->phyaddr,regnum)
271
272 #define TBIANA_SETTINGS ( \
273                 TBIANA_ASYMMETRIC_PAUSE \
274                 | TBIANA_SYMMETRIC_PAUSE \
275                 | TBIANA_FULL_DUPLEX \
276                 )
277
278 #define TBICR_SETTINGS ( \
279                 TBICR_PHY_RESET \
280                 | TBICR_ANEG_ENABLE \
281                 | TBICR_FULL_DUPLEX \
282                 | TBICR_SPEED1_SET \
283                 )
284 /* Configure the TBI for SGMII operation */
285 static void tsec_configure_serdes(struct tsec_private *priv)
286 {
287         /* Access TBI PHY registers at given TSEC register offset as opposed to the
288          * register offset used for external PHY accesses */
289         tsec_local_mdio_write(priv->regs, priv->regs->tbipa, TBI_ANA,
290                         TBIANA_SETTINGS);
291         tsec_local_mdio_write(priv->regs, priv->regs->tbipa, TBI_TBICON,
292                         TBICON_CLK_SELECT);
293         tsec_local_mdio_write(priv->regs, priv->regs->tbipa, TBI_CR,
294                         TBICR_SETTINGS);
295 }
296
297 /* Discover which PHY is attached to the device, and configure it
298  * properly.  If the PHY is not recognized, then return 0
299  * (failure).  Otherwise, return 1
300  */
301 static int init_phy(struct eth_device *dev)
302 {
303         struct tsec_private *priv = (struct tsec_private *)dev->priv;
304         struct phy_info *curphy;
305         volatile tsec_t *phyregs = priv->phyregs;
306         volatile tsec_t *regs = priv->regs;
307
308         /* Assign a Physical address to the TBI */
309         regs->tbipa = CONFIG_SYS_TBIPA_VALUE;
310         phyregs->tbipa = CONFIG_SYS_TBIPA_VALUE;
311         asm("sync");
312
313         /* Reset MII (due to new addresses) */
314         priv->phyregs->miimcfg = MIIMCFG_RESET;
315         asm("sync");
316         priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE;
317         asm("sync");
318         while (priv->phyregs->miimind & MIIMIND_BUSY) ;
319
320         if (0 == relocated)
321                 relocate_cmds();
322
323         /* Get the cmd structure corresponding to the attached
324          * PHY */
325         curphy = get_phy_info(dev);
326
327         if (curphy == NULL) {
328                 priv->phyinfo = NULL;
329                 printf("%s: No PHY found\n", dev->name);
330
331                 return 0;
332         }
333
334         if (regs->ecntrl & ECNTRL_SGMII_MODE)
335                 tsec_configure_serdes(priv);
336
337         priv->phyinfo = curphy;
338
339         phy_run_commands(priv, priv->phyinfo->config);
340
341         return 1;
342 }
343
344 /*
345  * Returns which value to write to the control register.
346  * For 10/100, the value is slightly different
347  */
348 uint mii_cr_init(uint mii_reg, struct tsec_private * priv)
349 {
350         if (priv->flags & TSEC_GIGABIT)
351                 return MIIM_CONTROL_INIT;
352         else
353                 return MIIM_CR_INIT;
354 }
355
356 /* Parse the status register for link, and then do
357  * auto-negotiation
358  */
359 uint mii_parse_sr(uint mii_reg, struct tsec_private * priv)
360 {
361         /*
362          * Wait if the link is up, and autonegotiation is in progress
363          * (ie - we're capable and it's not done)
364          */
365         mii_reg = read_phy_reg(priv, MIIM_STATUS);
366         if ((mii_reg & MIIM_STATUS_LINK) && (mii_reg & PHY_BMSR_AUTN_ABLE)
367             && !(mii_reg & PHY_BMSR_AUTN_COMP)) {
368                 int i = 0;
369
370                 puts("Waiting for PHY auto negotiation to complete");
371                 while (!(mii_reg & PHY_BMSR_AUTN_COMP)) {
372                         /*
373                          * Timeout reached ?
374                          */
375                         if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
376                                 puts(" TIMEOUT !\n");
377                                 priv->link = 0;
378                                 return 0;
379                         }
380
381                         if ((i++ % 1000) == 0) {
382                                 putc('.');
383                         }
384                         udelay(1000);   /* 1 ms */
385                         mii_reg = read_phy_reg(priv, MIIM_STATUS);
386                 }
387                 puts(" done\n");
388                 priv->link = 1;
389                 udelay(500000); /* another 500 ms (results in faster booting) */
390         } else {
391                 if (mii_reg & MIIM_STATUS_LINK)
392                         priv->link = 1;
393                 else
394                         priv->link = 0;
395         }
396
397         return 0;
398 }
399
400 /* Generic function which updates the speed and duplex.  If
401  * autonegotiation is enabled, it uses the AND of the link
402  * partner's advertised capabilities and our advertised
403  * capabilities.  If autonegotiation is disabled, we use the
404  * appropriate bits in the control register.
405  *
406  * Stolen from Linux's mii.c and phy_device.c
407  */
408 uint mii_parse_link(uint mii_reg, struct tsec_private *priv)
409 {
410         /* We're using autonegotiation */
411         if (mii_reg & PHY_BMSR_AUTN_ABLE) {
412                 uint lpa = 0;
413                 uint gblpa = 0;
414
415                 /* Check for gigabit capability */
416                 if (mii_reg & PHY_BMSR_EXT) {
417                         /* We want a list of states supported by
418                          * both PHYs in the link
419                          */
420                         gblpa = read_phy_reg(priv, PHY_1000BTSR);
421                         gblpa &= read_phy_reg(priv, PHY_1000BTCR) << 2;
422                 }
423
424                 /* Set the baseline so we only have to set them
425                  * if they're different
426                  */
427                 priv->speed = 10;
428                 priv->duplexity = 0;
429
430                 /* Check the gigabit fields */
431                 if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) {
432                         priv->speed = 1000;
433
434                         if (gblpa & PHY_1000BTSR_1000FD)
435                                 priv->duplexity = 1;
436
437                         /* We're done! */
438                         return 0;
439                 }
440
441                 lpa = read_phy_reg(priv, PHY_ANAR);
442                 lpa &= read_phy_reg(priv, PHY_ANLPAR);
443
444                 if (lpa & (PHY_ANLPAR_TXFD | PHY_ANLPAR_TX)) {
445                         priv->speed = 100;
446
447                         if (lpa & PHY_ANLPAR_TXFD)
448                                 priv->duplexity = 1;
449
450                 } else if (lpa & PHY_ANLPAR_10FD)
451                         priv->duplexity = 1;
452         } else {
453                 uint bmcr = read_phy_reg(priv, PHY_BMCR);
454
455                 priv->speed = 10;
456                 priv->duplexity = 0;
457
458                 if (bmcr & PHY_BMCR_DPLX)
459                         priv->duplexity = 1;
460
461                 if (bmcr & PHY_BMCR_1000_MBPS)
462                         priv->speed = 1000;
463                 else if (bmcr & PHY_BMCR_100_MBPS)
464                         priv->speed = 100;
465         }
466
467         return 0;
468 }
469
470 /*
471  * Parse the BCM54xx status register for speed and duplex information.
472  * The linux sungem_phy has this information, but in a table format.
473  */
474 uint mii_parse_BCM54xx_sr(uint mii_reg, struct tsec_private *priv)
475 {
476
477         switch((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >> MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT){
478
479                 case 1:
480                         printf("Enet starting in 10BT/HD\n");
481                         priv->duplexity = 0;
482                         priv->speed = 10;
483                         break;
484
485                 case 2:
486                         printf("Enet starting in 10BT/FD\n");
487                         priv->duplexity = 1;
488                         priv->speed = 10;
489                         break;
490
491                 case 3:
492                         printf("Enet starting in 100BT/HD\n");
493                         priv->duplexity = 0;
494                         priv->speed = 100;
495                         break;
496
497                 case 5:
498                         printf("Enet starting in 100BT/FD\n");
499                         priv->duplexity = 1;
500                         priv->speed = 100;
501                         break;
502
503                 case 6:
504                         printf("Enet starting in 1000BT/HD\n");
505                         priv->duplexity = 0;
506                         priv->speed = 1000;
507                         break;
508
509                 case 7:
510                         printf("Enet starting in 1000BT/FD\n");
511                         priv->duplexity = 1;
512                         priv->speed = 1000;
513                         break;
514
515                 default:
516                         printf("Auto-neg error, defaulting to 10BT/HD\n");
517                         priv->duplexity = 0;
518                         priv->speed = 10;
519                         break;
520         }
521
522         return 0;
523
524 }
525 /* Parse the 88E1011's status register for speed and duplex
526  * information
527  */
528 uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv)
529 {
530         uint speed;
531
532         mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
533
534         if ((mii_reg & MIIM_88E1011_PHYSTAT_LINK) &&
535                 !(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) {
536                 int i = 0;
537
538                 puts("Waiting for PHY realtime link");
539                 while (!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) {
540                         /* Timeout reached ? */
541                         if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
542                                 puts(" TIMEOUT !\n");
543                                 priv->link = 0;
544                                 break;
545                         }
546
547                         if ((i++ % 1000) == 0) {
548                                 putc('.');
549                         }
550                         udelay(1000);   /* 1 ms */
551                         mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
552                 }
553                 puts(" done\n");
554                 udelay(500000); /* another 500 ms (results in faster booting) */
555         } else {
556                 if (mii_reg & MIIM_88E1011_PHYSTAT_LINK)
557                         priv->link = 1;
558                 else
559                         priv->link = 0;
560         }
561
562         if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
563                 priv->duplexity = 1;
564         else
565                 priv->duplexity = 0;
566
567         speed = (mii_reg & MIIM_88E1011_PHYSTAT_SPEED);
568
569         switch (speed) {
570         case MIIM_88E1011_PHYSTAT_GBIT:
571                 priv->speed = 1000;
572                 break;
573         case MIIM_88E1011_PHYSTAT_100:
574                 priv->speed = 100;
575                 break;
576         default:
577                 priv->speed = 10;
578         }
579
580         return 0;
581 }
582
583 /* Parse the RTL8211B's status register for speed and duplex
584  * information
585  */
586 uint mii_parse_RTL8211B_sr(uint mii_reg, struct tsec_private * priv)
587 {
588         uint speed;
589
590         mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS);
591         if (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
592                 int i = 0;
593
594                 /* in case of timeout ->link is cleared */
595                 priv->link = 1;
596                 puts("Waiting for PHY realtime link");
597                 while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
598                         /* Timeout reached ? */
599                         if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
600                                 puts(" TIMEOUT !\n");
601                                 priv->link = 0;
602                                 break;
603                         }
604
605                         if ((i++ % 1000) == 0) {
606                                 putc('.');
607                         }
608                         udelay(1000);   /* 1 ms */
609                         mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS);
610                 }
611                 puts(" done\n");
612                 udelay(500000); /* another 500 ms (results in faster booting) */
613         } else {
614                 if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK)
615                         priv->link = 1;
616                 else
617                         priv->link = 0;
618         }
619
620         if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX)
621                 priv->duplexity = 1;
622         else
623                 priv->duplexity = 0;
624
625         speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED);
626
627         switch (speed) {
628         case MIIM_RTL8211B_PHYSTAT_GBIT:
629                 priv->speed = 1000;
630                 break;
631         case MIIM_RTL8211B_PHYSTAT_100:
632                 priv->speed = 100;
633                 break;
634         default:
635                 priv->speed = 10;
636         }
637
638         return 0;
639 }
640
641 /* Parse the cis8201's status register for speed and duplex
642  * information
643  */
644 uint mii_parse_cis8201(uint mii_reg, struct tsec_private * priv)
645 {
646         uint speed;
647
648         if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
649                 priv->duplexity = 1;
650         else
651                 priv->duplexity = 0;
652
653         speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
654         switch (speed) {
655         case MIIM_CIS8201_AUXCONSTAT_GBIT:
656                 priv->speed = 1000;
657                 break;
658         case MIIM_CIS8201_AUXCONSTAT_100:
659                 priv->speed = 100;
660                 break;
661         default:
662                 priv->speed = 10;
663                 break;
664         }
665
666         return 0;
667 }
668
669 /* Parse the vsc8244's status register for speed and duplex
670  * information
671  */
672 uint mii_parse_vsc8244(uint mii_reg, struct tsec_private * priv)
673 {
674         uint speed;
675
676         if (mii_reg & MIIM_VSC8244_AUXCONSTAT_DUPLEX)
677                 priv->duplexity = 1;
678         else
679                 priv->duplexity = 0;
680
681         speed = mii_reg & MIIM_VSC8244_AUXCONSTAT_SPEED;
682         switch (speed) {
683         case MIIM_VSC8244_AUXCONSTAT_GBIT:
684                 priv->speed = 1000;
685                 break;
686         case MIIM_VSC8244_AUXCONSTAT_100:
687                 priv->speed = 100;
688                 break;
689         default:
690                 priv->speed = 10;
691                 break;
692         }
693
694         return 0;
695 }
696
697 /* Parse the DM9161's status register for speed and duplex
698  * information
699  */
700 uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private * priv)
701 {
702         if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
703                 priv->speed = 100;
704         else
705                 priv->speed = 10;
706
707         if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
708                 priv->duplexity = 1;
709         else
710                 priv->duplexity = 0;
711
712         return 0;
713 }
714
715 /*
716  * Hack to write all 4 PHYs with the LED values
717  */
718 uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv)
719 {
720         uint phyid;
721         volatile tsec_t *regbase = priv->phyregs;
722         int timeout = 1000000;
723
724         for (phyid = 0; phyid < 4; phyid++) {
725                 regbase->miimadd = (phyid << 8) | mii_reg;
726                 regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT;
727                 asm("sync");
728
729                 timeout = 1000000;
730                 while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ;
731         }
732
733         return MIIM_CIS8204_SLEDCON_INIT;
734 }
735
736 uint mii_cis8204_setmode(uint mii_reg, struct tsec_private * priv)
737 {
738         if (priv->flags & TSEC_REDUCED)
739                 return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII;
740         else
741                 return MIIM_CIS8204_EPHYCON_INIT;
742 }
743
744 uint mii_m88e1111s_setmode(uint mii_reg, struct tsec_private *priv)
745 {
746         uint mii_data = read_phy_reg(priv, mii_reg);
747
748         if (priv->flags & TSEC_REDUCED)
749                 mii_data = (mii_data & 0xfff0) | 0x000b;
750         return mii_data;
751 }
752
753 /* Initialized required registers to appropriate values, zeroing
754  * those we don't care about (unless zero is bad, in which case,
755  * choose a more appropriate value)
756  */
757 static void init_registers(volatile tsec_t * regs)
758 {
759         /* Clear IEVENT */
760         regs->ievent = IEVENT_INIT_CLEAR;
761
762         regs->imask = IMASK_INIT_CLEAR;
763
764         regs->hash.iaddr0 = 0;
765         regs->hash.iaddr1 = 0;
766         regs->hash.iaddr2 = 0;
767         regs->hash.iaddr3 = 0;
768         regs->hash.iaddr4 = 0;
769         regs->hash.iaddr5 = 0;
770         regs->hash.iaddr6 = 0;
771         regs->hash.iaddr7 = 0;
772
773         regs->hash.gaddr0 = 0;
774         regs->hash.gaddr1 = 0;
775         regs->hash.gaddr2 = 0;
776         regs->hash.gaddr3 = 0;
777         regs->hash.gaddr4 = 0;
778         regs->hash.gaddr5 = 0;
779         regs->hash.gaddr6 = 0;
780         regs->hash.gaddr7 = 0;
781
782         regs->rctrl = 0x00000000;
783
784         /* Init RMON mib registers */
785         memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
786
787         regs->rmon.cam1 = 0xffffffff;
788         regs->rmon.cam2 = 0xffffffff;
789
790         regs->mrblr = MRBLR_INIT_SETTINGS;
791
792         regs->minflr = MINFLR_INIT_SETTINGS;
793
794         regs->attr = ATTR_INIT_SETTINGS;
795         regs->attreli = ATTRELI_INIT_SETTINGS;
796
797 }
798
799 /* Configure maccfg2 based on negotiated speed and duplex
800  * reported by PHY handling code
801  */
802 static void adjust_link(struct eth_device *dev)
803 {
804         struct tsec_private *priv = (struct tsec_private *)dev->priv;
805         volatile tsec_t *regs = priv->regs;
806
807         if (priv->link) {
808                 if (priv->duplexity != 0)
809                         regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
810                 else
811                         regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX);
812
813                 switch (priv->speed) {
814                 case 1000:
815                         regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF))
816                                          | MACCFG2_GMII);
817                         break;
818                 case 100:
819                 case 10:
820                         regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF))
821                                          | MACCFG2_MII);
822
823                         /* Set R100 bit in all modes although
824                          * it is only used in RGMII mode
825                          */
826                         if (priv->speed == 100)
827                                 regs->ecntrl |= ECNTRL_R100;
828                         else
829                                 regs->ecntrl &= ~(ECNTRL_R100);
830                         break;
831                 default:
832                         printf("%s: Speed was bad\n", dev->name);
833                         break;
834                 }
835
836                 printf("Speed: %d, %s duplex\n", priv->speed,
837                        (priv->duplexity) ? "full" : "half");
838
839         } else {
840                 printf("%s: No link.\n", dev->name);
841         }
842 }
843
844 /* Set up the buffers and their descriptors, and bring up the
845  * interface
846  */
847 static void startup_tsec(struct eth_device *dev)
848 {
849         int i;
850         struct tsec_private *priv = (struct tsec_private *)dev->priv;
851         volatile tsec_t *regs = priv->regs;
852
853         /* Point to the buffer descriptors */
854         regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
855         regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
856
857         /* Initialize the Rx Buffer descriptors */
858         for (i = 0; i < PKTBUFSRX; i++) {
859                 rtx.rxbd[i].status = RXBD_EMPTY;
860                 rtx.rxbd[i].length = 0;
861                 rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i];
862         }
863         rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP;
864
865         /* Initialize the TX Buffer Descriptors */
866         for (i = 0; i < TX_BUF_CNT; i++) {
867                 rtx.txbd[i].status = 0;
868                 rtx.txbd[i].length = 0;
869                 rtx.txbd[i].bufPtr = 0;
870         }
871         rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP;
872
873         /* Start up the PHY */
874         if(priv->phyinfo)
875                 phy_run_commands(priv, priv->phyinfo->startup);
876
877         adjust_link(dev);
878
879         /* Enable Transmit and Receive */
880         regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
881
882         /* Tell the DMA it is clear to go */
883         regs->dmactrl |= DMACTRL_INIT_SETTINGS;
884         regs->tstat = TSTAT_CLEAR_THALT;
885         regs->rstat = RSTAT_CLEAR_RHALT;
886         regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
887 }
888
889 /* This returns the status bits of the device.  The return value
890  * is never checked, and this is what the 8260 driver did, so we
891  * do the same.  Presumably, this would be zero if there were no
892  * errors
893  */
894 static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
895 {
896         int i;
897         int result = 0;
898         struct tsec_private *priv = (struct tsec_private *)dev->priv;
899         volatile tsec_t *regs = priv->regs;
900
901         /* Find an empty buffer descriptor */
902         for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
903                 if (i >= TOUT_LOOP) {
904                         debug("%s: tsec: tx buffers full\n", dev->name);
905                         return result;
906                 }
907         }
908
909         rtx.txbd[txIdx].bufPtr = (uint) packet;
910         rtx.txbd[txIdx].length = length;
911         rtx.txbd[txIdx].status |=
912             (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
913
914         /* Tell the DMA to go */
915         regs->tstat = TSTAT_CLEAR_THALT;
916
917         /* Wait for buffer to be transmitted */
918         for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
919                 if (i >= TOUT_LOOP) {
920                         debug("%s: tsec: tx error\n", dev->name);
921                         return result;
922                 }
923         }
924
925         txIdx = (txIdx + 1) % TX_BUF_CNT;
926         result = rtx.txbd[txIdx].status & TXBD_STATS;
927
928         return result;
929 }
930
931 static int tsec_recv(struct eth_device *dev)
932 {
933         int length;
934         struct tsec_private *priv = (struct tsec_private *)dev->priv;
935         volatile tsec_t *regs = priv->regs;
936
937         while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
938
939                 length = rtx.rxbd[rxIdx].length;
940
941                 /* Send the packet up if there were no errors */
942                 if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
943                         NetReceive(NetRxPackets[rxIdx], length - 4);
944                 } else {
945                         printf("Got error %x\n",
946                                (rtx.rxbd[rxIdx].status & RXBD_STATS));
947                 }
948
949                 rtx.rxbd[rxIdx].length = 0;
950
951                 /* Set the wrap bit if this is the last element in the list */
952                 rtx.rxbd[rxIdx].status =
953                     RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
954
955                 rxIdx = (rxIdx + 1) % PKTBUFSRX;
956         }
957
958         if (regs->ievent & IEVENT_BSY) {
959                 regs->ievent = IEVENT_BSY;
960                 regs->rstat = RSTAT_CLEAR_RHALT;
961         }
962
963         return -1;
964
965 }
966
967 /* Stop the interface */
968 static void tsec_halt(struct eth_device *dev)
969 {
970         struct tsec_private *priv = (struct tsec_private *)dev->priv;
971         volatile tsec_t *regs = priv->regs;
972
973         regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
974         regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
975
976         while (!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC))) ;
977
978         regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
979
980         /* Shut down the PHY, as needed */
981         if(priv->phyinfo)
982                 phy_run_commands(priv, priv->phyinfo->shutdown);
983 }
984
985 struct phy_info phy_info_M88E1149S = {
986         0x1410ca,
987         "Marvell 88E1149S",
988         4,
989         (struct phy_cmd[]){     /* config */
990                 /* Reset and configure the PHY */
991                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
992                 {0x1d, 0x1f, NULL},
993                 {0x1e, 0x200c, NULL},
994                 {0x1d, 0x5, NULL},
995                 {0x1e, 0x0, NULL},
996                 {0x1e, 0x100, NULL},
997                 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
998                 {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
999                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1000                 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1001                 {miim_end,}
1002         },
1003         (struct phy_cmd[]){     /* startup */
1004                 /* Status is read once to clear old link state */
1005                 {MIIM_STATUS, miim_read, NULL},
1006                 /* Auto-negotiate */
1007                 {MIIM_STATUS, miim_read, &mii_parse_sr},
1008                 /* Read the status */
1009                 {MIIM_88E1011_PHY_STATUS, miim_read,
1010                  &mii_parse_88E1011_psr},
1011                 {miim_end,}
1012         },
1013         (struct phy_cmd[]){     /* shutdown */
1014                 {miim_end,}
1015         },
1016 };
1017
1018 /* The 5411 id is 0x206070, the 5421 is 0x2060e0 */
1019 struct phy_info phy_info_BCM5461S = {
1020         0x02060c1,      /* 5461 ID */
1021         "Broadcom BCM5461S",
1022         0, /* not clear to me what minor revisions we can shift away */
1023         (struct phy_cmd[]) { /* config */
1024                 /* Reset and configure the PHY */
1025                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1026                 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
1027                 {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
1028                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1029                 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1030                 {miim_end,}
1031         },
1032         (struct phy_cmd[]) { /* startup */
1033                 /* Status is read once to clear old link state */
1034                 {MIIM_STATUS, miim_read, NULL},
1035                 /* Auto-negotiate */
1036                 {MIIM_STATUS, miim_read, &mii_parse_sr},
1037                 /* Read the status */
1038                 {MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr},
1039                 {miim_end,}
1040         },
1041         (struct phy_cmd[]) { /* shutdown */
1042                 {miim_end,}
1043         },
1044 };
1045
1046 struct phy_info phy_info_BCM5464S = {
1047         0x02060b1,      /* 5464 ID */
1048         "Broadcom BCM5464S",
1049         0, /* not clear to me what minor revisions we can shift away */
1050         (struct phy_cmd[]) { /* config */
1051                 /* Reset and configure the PHY */
1052                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1053                 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
1054                 {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
1055                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1056                 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1057                 {miim_end,}
1058         },
1059         (struct phy_cmd[]) { /* startup */
1060                 /* Status is read once to clear old link state */
1061                 {MIIM_STATUS, miim_read, NULL},
1062                 /* Auto-negotiate */
1063                 {MIIM_STATUS, miim_read, &mii_parse_sr},
1064                 /* Read the status */
1065                 {MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr},
1066                 {miim_end,}
1067         },
1068         (struct phy_cmd[]) { /* shutdown */
1069                 {miim_end,}
1070         },
1071 };
1072
1073 struct phy_info phy_info_M88E1011S = {
1074         0x01410c6,
1075         "Marvell 88E1011S",
1076         4,
1077         (struct phy_cmd[]){     /* config */
1078                            /* Reset and configure the PHY */
1079                            {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1080                            {0x1d, 0x1f, NULL},
1081                            {0x1e, 0x200c, NULL},
1082                            {0x1d, 0x5, NULL},
1083                            {0x1e, 0x0, NULL},
1084                            {0x1e, 0x100, NULL},
1085                            {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
1086                            {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
1087                            {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1088                            {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1089                            {miim_end,}
1090                            },
1091         (struct phy_cmd[]){     /* startup */
1092                            /* Status is read once to clear old link state */
1093                            {MIIM_STATUS, miim_read, NULL},
1094                            /* Auto-negotiate */
1095                            {MIIM_STATUS, miim_read, &mii_parse_sr},
1096                            /* Read the status */
1097                            {MIIM_88E1011_PHY_STATUS, miim_read,
1098                             &mii_parse_88E1011_psr},
1099                            {miim_end,}
1100                            },
1101         (struct phy_cmd[]){     /* shutdown */
1102                            {miim_end,}
1103                            },
1104 };
1105
1106 struct phy_info phy_info_M88E1111S = {
1107         0x01410cc,
1108         "Marvell 88E1111S",
1109         4,
1110         (struct phy_cmd[]){     /* config */
1111                            /* Reset and configure the PHY */
1112                            {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1113                            {0x1b, 0x848f, &mii_m88e1111s_setmode},
1114                            {0x14, 0x0cd2, NULL}, /* Delay RGMII TX and RX */
1115                            {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
1116                            {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
1117                            {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1118                            {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1119                            {miim_end,}
1120                            },
1121         (struct phy_cmd[]){     /* startup */
1122                            /* Status is read once to clear old link state */
1123                            {MIIM_STATUS, miim_read, NULL},
1124                            /* Auto-negotiate */
1125                            {MIIM_STATUS, miim_read, &mii_parse_sr},
1126                            /* Read the status */
1127                            {MIIM_88E1011_PHY_STATUS, miim_read,
1128                             &mii_parse_88E1011_psr},
1129                            {miim_end,}
1130                            },
1131         (struct phy_cmd[]){     /* shutdown */
1132                            {miim_end,}
1133                            },
1134 };
1135
1136 struct phy_info phy_info_M88E1118 = {
1137         0x01410e1,
1138         "Marvell 88E1118",
1139         4,
1140         (struct phy_cmd[]){     /* config */
1141                 /* Reset and configure the PHY */
1142                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1143                 {0x16, 0x0002, NULL}, /* Change Page Number */
1144                 {0x15, 0x1070, NULL}, /* Delay RGMII TX and RX */
1145                 {0x16, 0x0003, NULL}, /* Change Page Number */
1146                 {0x10, 0x021e, NULL}, /* Adjust LED control */
1147                 {0x16, 0x0000, NULL}, /* Change Page Number */
1148                 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
1149                 {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
1150                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1151                 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1152                 {miim_end,}
1153                 },
1154         (struct phy_cmd[]){     /* startup */
1155                 {0x16, 0x0000, NULL}, /* Change Page Number */
1156                 /* Status is read once to clear old link state */
1157                 {MIIM_STATUS, miim_read, NULL},
1158                 /* Auto-negotiate */
1159                 {MIIM_STATUS, miim_read, &mii_parse_sr},
1160                 /* Read the status */
1161                 {MIIM_88E1011_PHY_STATUS, miim_read,
1162                  &mii_parse_88E1011_psr},
1163                 {miim_end,}
1164                 },
1165         (struct phy_cmd[]){     /* shutdown */
1166                 {miim_end,}
1167                 },
1168 };
1169
1170 /*
1171  *  Since to access LED register we need do switch the page, we
1172  * do LED configuring in the miim_read-like function as follows
1173  */
1174 uint mii_88E1121_set_led (uint mii_reg, struct tsec_private *priv)
1175 {
1176         uint pg;
1177
1178         /* Switch the page to access the led register */
1179         pg = read_phy_reg(priv, MIIM_88E1121_PHY_PAGE);
1180         write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, MIIM_88E1121_PHY_LED_PAGE);
1181
1182         /* Configure leds */
1183         write_phy_reg(priv, MIIM_88E1121_PHY_LED_CTRL,
1184                       MIIM_88E1121_PHY_LED_DEF);
1185
1186         /* Restore the page pointer */
1187         write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, pg);
1188         return 0;
1189 }
1190
1191 struct phy_info phy_info_M88E1121R = {
1192         0x01410cb,
1193         "Marvell 88E1121R",
1194         4,
1195         (struct phy_cmd[]){     /* config */
1196                            /* Reset and configure the PHY */
1197                            {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1198                            {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
1199                            {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
1200                            /* Configure leds */
1201                            {MIIM_88E1121_PHY_LED_CTRL, miim_read,
1202                             &mii_88E1121_set_led},
1203                            {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1204                            /* Disable IRQs and de-assert interrupt */
1205                            {MIIM_88E1121_PHY_IRQ_EN, 0, NULL},
1206                            {MIIM_88E1121_PHY_IRQ_STATUS, miim_read, NULL},
1207                            {miim_end,}
1208                            },
1209         (struct phy_cmd[]){     /* startup */
1210                            /* Status is read once to clear old link state */
1211                            {MIIM_STATUS, miim_read, NULL},
1212                            {MIIM_STATUS, miim_read, &mii_parse_sr},
1213                            {MIIM_STATUS, miim_read, &mii_parse_link},
1214                            {miim_end,}
1215                            },
1216         (struct phy_cmd[]){     /* shutdown */
1217                            {miim_end,}
1218                            },
1219 };
1220
1221 static unsigned int m88e1145_setmode(uint mii_reg, struct tsec_private *priv)
1222 {
1223         uint mii_data = read_phy_reg(priv, mii_reg);
1224
1225         /* Setting MIIM_88E1145_PHY_EXT_CR */
1226         if (priv->flags & TSEC_REDUCED)
1227                 return mii_data |
1228                     MIIM_M88E1145_RGMII_RX_DELAY | MIIM_M88E1145_RGMII_TX_DELAY;
1229         else
1230                 return mii_data;
1231 }
1232
1233 static struct phy_info phy_info_M88E1145 = {
1234         0x01410cd,
1235         "Marvell 88E1145",
1236         4,
1237         (struct phy_cmd[]){     /* config */
1238                            /* Reset the PHY */
1239                            {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1240
1241                            /* Errata E0, E1 */
1242                            {29, 0x001b, NULL},
1243                            {30, 0x418f, NULL},
1244                            {29, 0x0016, NULL},
1245                            {30, 0xa2da, NULL},
1246
1247                            /* Configure the PHY */
1248                            {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
1249                            {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
1250                            {MIIM_88E1011_PHY_SCR, MIIM_88E1011_PHY_MDI_X_AUTO,
1251                             NULL},
1252                            {MIIM_88E1145_PHY_EXT_CR, 0, &m88e1145_setmode},
1253                            {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1254                            {MIIM_CONTROL, MIIM_CONTROL_INIT, NULL},
1255                            {miim_end,}
1256                            },
1257         (struct phy_cmd[]){     /* startup */
1258                            /* Status is read once to clear old link state */
1259                            {MIIM_STATUS, miim_read, NULL},
1260                            /* Auto-negotiate */
1261                            {MIIM_STATUS, miim_read, &mii_parse_sr},
1262                            {MIIM_88E1111_PHY_LED_CONTROL,
1263                             MIIM_88E1111_PHY_LED_DIRECT, NULL},
1264                            /* Read the Status */
1265                            {MIIM_88E1011_PHY_STATUS, miim_read,
1266                             &mii_parse_88E1011_psr},
1267                            {miim_end,}
1268                            },
1269         (struct phy_cmd[]){     /* shutdown */
1270                            {miim_end,}
1271                            },
1272 };
1273
1274 struct phy_info phy_info_cis8204 = {
1275         0x3f11,
1276         "Cicada Cis8204",
1277         6,
1278         (struct phy_cmd[]){     /* config */
1279                            /* Override PHY config settings */
1280                            {MIIM_CIS8201_AUX_CONSTAT,
1281                             MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
1282                            /* Configure some basic stuff */
1283                            {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1284                            {MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT,
1285                             &mii_cis8204_fixled},
1286                            {MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT,
1287                             &mii_cis8204_setmode},
1288                            {miim_end,}
1289                            },
1290         (struct phy_cmd[]){     /* startup */
1291                            /* Read the Status (2x to make sure link is right) */
1292                            {MIIM_STATUS, miim_read, NULL},
1293                            /* Auto-negotiate */
1294                            {MIIM_STATUS, miim_read, &mii_parse_sr},
1295                            /* Read the status */
1296                            {MIIM_CIS8201_AUX_CONSTAT, miim_read,
1297                             &mii_parse_cis8201},
1298                            {miim_end,}
1299                            },
1300         (struct phy_cmd[]){     /* shutdown */
1301                            {miim_end,}
1302                            },
1303 };
1304
1305 /* Cicada 8201 */
1306 struct phy_info phy_info_cis8201 = {
1307         0xfc41,
1308         "CIS8201",
1309         4,
1310         (struct phy_cmd[]){     /* config */
1311                            /* Override PHY config settings */
1312                            {MIIM_CIS8201_AUX_CONSTAT,
1313                             MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
1314                            /* Set up the interface mode */
1315                            {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT,
1316                             NULL},
1317                            /* Configure some basic stuff */
1318                            {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1319                            {miim_end,}
1320                            },
1321         (struct phy_cmd[]){     /* startup */
1322                            /* Read the Status (2x to make sure link is right) */
1323                            {MIIM_STATUS, miim_read, NULL},
1324                            /* Auto-negotiate */
1325                            {MIIM_STATUS, miim_read, &mii_parse_sr},
1326                            /* Read the status */
1327                            {MIIM_CIS8201_AUX_CONSTAT, miim_read,
1328                             &mii_parse_cis8201},
1329                            {miim_end,}
1330                            },
1331         (struct phy_cmd[]){     /* shutdown */
1332                            {miim_end,}
1333                            },
1334 };
1335 struct phy_info phy_info_VSC8211 = {
1336         0xfc4b,
1337         "Vitesse VSC8211",
1338         4,
1339         (struct phy_cmd[]) { /* config */
1340                            /* Override PHY config settings */
1341                            {MIIM_CIS8201_AUX_CONSTAT,
1342                             MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
1343                            /* Set up the interface mode */
1344                            {MIIM_CIS8201_EXT_CON1,
1345                             MIIM_CIS8201_EXTCON1_INIT, NULL},
1346                            /* Configure some basic stuff */
1347                            {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1348                            {miim_end,}
1349                            },
1350         (struct phy_cmd[]) { /* startup */
1351                            /* Read the Status (2x to make sure link is right) */
1352                            {MIIM_STATUS, miim_read, NULL},
1353                            /* Auto-negotiate */
1354                            {MIIM_STATUS, miim_read, &mii_parse_sr},
1355                            /* Read the status */
1356                            {MIIM_CIS8201_AUX_CONSTAT, miim_read,
1357                             &mii_parse_cis8201},
1358                            {miim_end,}
1359                            },
1360         (struct phy_cmd[]) { /* shutdown */
1361                            {miim_end,}
1362         },
1363 };
1364 struct phy_info phy_info_VSC8244 = {
1365         0x3f1b,
1366         "Vitesse VSC8244",
1367         6,
1368         (struct phy_cmd[]){     /* config */
1369                            /* Override PHY config settings */
1370                            /* Configure some basic stuff */
1371                            {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1372                            {miim_end,}
1373                            },
1374         (struct phy_cmd[]){     /* startup */
1375                            /* Read the Status (2x to make sure link is right) */
1376                            {MIIM_STATUS, miim_read, NULL},
1377                            /* Auto-negotiate */
1378                            {MIIM_STATUS, miim_read, &mii_parse_sr},
1379                            /* Read the status */
1380                            {MIIM_VSC8244_AUX_CONSTAT, miim_read,
1381                             &mii_parse_vsc8244},
1382                            {miim_end,}
1383                            },
1384         (struct phy_cmd[]){     /* shutdown */
1385                            {miim_end,}
1386                            },
1387 };
1388
1389 struct phy_info phy_info_VSC8601 = {
1390                 0x00007042,
1391                 "Vitesse VSC8601",
1392                 4,
1393                 (struct phy_cmd[]){     /* config */
1394                                 /* Override PHY config settings */
1395                                 /* Configure some basic stuff */
1396                                 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1397 #ifdef CONFIG_SYS_VSC8601_SKEWFIX
1398                                 {MIIM_VSC8601_EPHY_CON,MIIM_VSC8601_EPHY_CON_INIT_SKEW,NULL},
1399 #if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX)
1400                                 {MIIM_EXT_PAGE_ACCESS,1,NULL},
1401 #define VSC8101_SKEW    (CONFIG_SYS_VSC8601_SKEW_TX<<14)|(CONFIG_SYS_VSC8601_SKEW_RX<<12)
1402                                 {MIIM_VSC8601_SKEW_CTRL,VSC8101_SKEW,NULL},
1403                                 {MIIM_EXT_PAGE_ACCESS,0,NULL},
1404 #endif
1405 #endif
1406                                 {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
1407                                 {MIIM_CONTROL, MIIM_CONTROL_RESTART, &mii_cr_init},
1408                                 {miim_end,}
1409                                  },
1410                 (struct phy_cmd[]){     /* startup */
1411                                 /* Read the Status (2x to make sure link is right) */
1412                                 {MIIM_STATUS, miim_read, NULL},
1413                                 /* Auto-negotiate */
1414                                 {MIIM_STATUS, miim_read, &mii_parse_sr},
1415                                 /* Read the status */
1416                                 {MIIM_VSC8244_AUX_CONSTAT, miim_read,
1417                                                 &mii_parse_vsc8244},
1418                                 {miim_end,}
1419                                 },
1420                 (struct phy_cmd[]){     /* shutdown */
1421                                 {miim_end,}
1422                                 },
1423 };
1424
1425
1426 struct phy_info phy_info_dm9161 = {
1427         0x0181b88,
1428         "Davicom DM9161E",
1429         4,
1430         (struct phy_cmd[]){     /* config */
1431                            {MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL},
1432                            /* Do not bypass the scrambler/descrambler */
1433                            {MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL},
1434                            /* Clear 10BTCSR to default */
1435                            {MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT,
1436                             NULL},
1437                            /* Configure some basic stuff */
1438                            {MIIM_CONTROL, MIIM_CR_INIT, NULL},
1439                            /* Restart Auto Negotiation */
1440                            {MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL},
1441                            {miim_end,}
1442                            },
1443         (struct phy_cmd[]){     /* startup */
1444                            /* Status is read once to clear old link state */
1445                            {MIIM_STATUS, miim_read, NULL},
1446                            /* Auto-negotiate */
1447                            {MIIM_STATUS, miim_read, &mii_parse_sr},
1448                            /* Read the status */
1449                            {MIIM_DM9161_SCSR, miim_read,
1450                             &mii_parse_dm9161_scsr},
1451                            {miim_end,}
1452                            },
1453         (struct phy_cmd[]){     /* shutdown */
1454                            {miim_end,}
1455                            },
1456 };
1457 /* a generic flavor.  */
1458 struct phy_info phy_info_generic =  {
1459         0,
1460         "Unknown/Generic PHY",
1461         32,
1462         (struct phy_cmd[]) { /* config */
1463                 {PHY_BMCR, PHY_BMCR_RESET, NULL},
1464                 {PHY_BMCR, PHY_BMCR_AUTON|PHY_BMCR_RST_NEG, NULL},
1465                 {miim_end,}
1466         },
1467         (struct phy_cmd[]) { /* startup */
1468                 {PHY_BMSR, miim_read, NULL},
1469                 {PHY_BMSR, miim_read, &mii_parse_sr},
1470                 {PHY_BMSR, miim_read, &mii_parse_link},
1471                 {miim_end,}
1472         },
1473         (struct phy_cmd[]) { /* shutdown */
1474                 {miim_end,}
1475         }
1476 };
1477
1478
1479 uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
1480 {
1481         unsigned int speed;
1482         if (priv->link) {
1483                 speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
1484
1485                 switch (speed) {
1486                 case MIIM_LXT971_SR2_10HDX:
1487                         priv->speed = 10;
1488                         priv->duplexity = 0;
1489                         break;
1490                 case MIIM_LXT971_SR2_10FDX:
1491                         priv->speed = 10;
1492                         priv->duplexity = 1;
1493                         break;
1494                 case MIIM_LXT971_SR2_100HDX:
1495                         priv->speed = 100;
1496                         priv->duplexity = 0;
1497                         break;
1498                 default:
1499                         priv->speed = 100;
1500                         priv->duplexity = 1;
1501                 }
1502         } else {
1503                 priv->speed = 0;
1504                 priv->duplexity = 0;
1505         }
1506
1507         return 0;
1508 }
1509
1510 static struct phy_info phy_info_lxt971 = {
1511         0x0001378e,
1512         "LXT971",
1513         4,
1514         (struct phy_cmd[]){     /* config */
1515                            {MIIM_CR, MIIM_CR_INIT, mii_cr_init},        /* autonegotiate */
1516                            {miim_end,}
1517                            },
1518         (struct phy_cmd[]){     /* startup - enable interrupts */
1519                            /* { 0x12, 0x00f2, NULL }, */
1520                            {MIIM_STATUS, miim_read, NULL},
1521                            {MIIM_STATUS, miim_read, &mii_parse_sr},
1522                            {MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2},
1523                            {miim_end,}
1524                            },
1525         (struct phy_cmd[]){     /* shutdown - disable interrupts */
1526                            {miim_end,}
1527                            },
1528 };
1529
1530 /* Parse the DP83865's link and auto-neg status register for speed and duplex
1531  * information
1532  */
1533 uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv)
1534 {
1535         switch (mii_reg & MIIM_DP83865_SPD_MASK) {
1536
1537         case MIIM_DP83865_SPD_1000:
1538                 priv->speed = 1000;
1539                 break;
1540
1541         case MIIM_DP83865_SPD_100:
1542                 priv->speed = 100;
1543                 break;
1544
1545         default:
1546                 priv->speed = 10;
1547                 break;
1548
1549         }
1550
1551         if (mii_reg & MIIM_DP83865_DPX_FULL)
1552                 priv->duplexity = 1;
1553         else
1554                 priv->duplexity = 0;
1555
1556         return 0;
1557 }
1558
1559 struct phy_info phy_info_dp83865 = {
1560         0x20005c7,
1561         "NatSemi DP83865",
1562         4,
1563         (struct phy_cmd[]){     /* config */
1564                            {MIIM_CONTROL, MIIM_DP83865_CR_INIT, NULL},
1565                            {miim_end,}
1566                            },
1567         (struct phy_cmd[]){     /* startup */
1568                            /* Status is read once to clear old link state */
1569                            {MIIM_STATUS, miim_read, NULL},
1570                            /* Auto-negotiate */
1571                            {MIIM_STATUS, miim_read, &mii_parse_sr},
1572                            /* Read the link and auto-neg status */
1573                            {MIIM_DP83865_LANR, miim_read,
1574                             &mii_parse_dp83865_lanr},
1575                            {miim_end,}
1576                            },
1577         (struct phy_cmd[]){     /* shutdown */
1578                            {miim_end,}
1579                            },
1580 };
1581
1582 struct phy_info phy_info_rtl8211b = {
1583         0x001cc91,
1584         "RealTek RTL8211B",
1585         4,
1586         (struct phy_cmd[]){     /* config */
1587                 /* Reset and configure the PHY */
1588                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1589                 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
1590                 {MIIM_ANAR, MIIM_ANAR_INIT, NULL},
1591                 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
1592                 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
1593                 {miim_end,}
1594         },
1595         (struct phy_cmd[]){     /* startup */
1596                 /* Status is read once to clear old link state */
1597                 {MIIM_STATUS, miim_read, NULL},
1598                 /* Auto-negotiate */
1599                 {MIIM_STATUS, miim_read, &mii_parse_sr},
1600                 /* Read the status */
1601                 {MIIM_RTL8211B_PHY_STATUS, miim_read, &mii_parse_RTL8211B_sr},
1602                 {miim_end,}
1603         },
1604         (struct phy_cmd[]){     /* shutdown */
1605                 {miim_end,}
1606         },
1607 };
1608
1609 struct phy_info *phy_info[] = {
1610         &phy_info_cis8204,
1611         &phy_info_cis8201,
1612         &phy_info_BCM5461S,
1613         &phy_info_BCM5464S,
1614         &phy_info_M88E1011S,
1615         &phy_info_M88E1111S,
1616         &phy_info_M88E1118,
1617         &phy_info_M88E1121R,
1618         &phy_info_M88E1145,
1619         &phy_info_M88E1149S,
1620         &phy_info_dm9161,
1621         &phy_info_lxt971,
1622         &phy_info_VSC8211,
1623         &phy_info_VSC8244,
1624         &phy_info_VSC8601,
1625         &phy_info_dp83865,
1626         &phy_info_rtl8211b,
1627         &phy_info_generic,      /* must be last; has ID 0 and 32 bit mask */
1628         NULL
1629 };
1630
1631 /* Grab the identifier of the device's PHY, and search through
1632  * all of the known PHYs to see if one matches.  If so, return
1633  * it, if not, return NULL
1634  */
1635 struct phy_info *get_phy_info(struct eth_device *dev)
1636 {
1637         struct tsec_private *priv = (struct tsec_private *)dev->priv;
1638         uint phy_reg, phy_ID;
1639         int i;
1640         struct phy_info *theInfo = NULL;
1641
1642         /* Grab the bits from PHYIR1, and put them in the upper half */
1643         phy_reg = read_phy_reg(priv, MIIM_PHYIR1);
1644         phy_ID = (phy_reg & 0xffff) << 16;
1645
1646         /* Grab the bits from PHYIR2, and put them in the lower half */
1647         phy_reg = read_phy_reg(priv, MIIM_PHYIR2);
1648         phy_ID |= (phy_reg & 0xffff);
1649
1650         /* loop through all the known PHY types, and find one that */
1651         /* matches the ID we read from the PHY. */
1652         for (i = 0; phy_info[i]; i++) {
1653                 if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) {
1654                         theInfo = phy_info[i];
1655                         break;
1656                 }
1657         }
1658
1659         if (theInfo == &phy_info_generic) {
1660                 printf("%s: No support for PHY id %x; assuming generic\n", dev->name, phy_ID);
1661         } else {
1662                 debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID);
1663         }
1664
1665         return theInfo;
1666 }
1667
1668 /* Execute the given series of commands on the given device's
1669  * PHY, running functions as necessary
1670  */
1671 void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
1672 {
1673         int i;
1674         uint result;
1675         volatile tsec_t *phyregs = priv->phyregs;
1676
1677         phyregs->miimcfg = MIIMCFG_RESET;
1678
1679         phyregs->miimcfg = MIIMCFG_INIT_VALUE;
1680
1681         while (phyregs->miimind & MIIMIND_BUSY) ;
1682
1683         for (i = 0; cmd->mii_reg != miim_end; i++) {
1684                 if (cmd->mii_data == miim_read) {
1685                         result = read_phy_reg(priv, cmd->mii_reg);
1686
1687                         if (cmd->funct != NULL)
1688                                 (*(cmd->funct)) (result, priv);
1689
1690                 } else {
1691                         if (cmd->funct != NULL)
1692                                 result = (*(cmd->funct)) (cmd->mii_reg, priv);
1693                         else
1694                                 result = cmd->mii_data;
1695
1696                         write_phy_reg(priv, cmd->mii_reg, result);
1697
1698                 }
1699                 cmd++;
1700         }
1701 }
1702
1703 /* Relocate the function pointers in the phy cmd lists */
1704 static void relocate_cmds(void)
1705 {
1706         struct phy_cmd **cmdlistptr;
1707         struct phy_cmd *cmd;
1708         int i, j, k;
1709
1710         for (i = 0; phy_info[i]; i++) {
1711                 /* First thing's first: relocate the pointers to the
1712                  * PHY command structures (the structs were done) */
1713                 phy_info[i] = (struct phy_info *)((uint) phy_info[i]
1714                                                   + gd->reloc_off);
1715                 phy_info[i]->name += gd->reloc_off;
1716                 phy_info[i]->config =
1717                     (struct phy_cmd *)((uint) phy_info[i]->config
1718                                        + gd->reloc_off);
1719                 phy_info[i]->startup =
1720                     (struct phy_cmd *)((uint) phy_info[i]->startup
1721                                        + gd->reloc_off);
1722                 phy_info[i]->shutdown =
1723                     (struct phy_cmd *)((uint) phy_info[i]->shutdown
1724                                        + gd->reloc_off);
1725
1726                 cmdlistptr = &phy_info[i]->config;
1727                 j = 0;
1728                 for (; cmdlistptr <= &phy_info[i]->shutdown; cmdlistptr++) {
1729                         k = 0;
1730                         for (cmd = *cmdlistptr;
1731                              cmd->mii_reg != miim_end;
1732                              cmd++) {
1733                                 /* Only relocate non-NULL pointers */
1734                                 if (cmd->funct)
1735                                         cmd->funct += gd->reloc_off;
1736
1737                                 k++;
1738                         }
1739                         j++;
1740                 }
1741         }
1742
1743         relocated = 1;
1744 }
1745
1746 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
1747         && !defined(BITBANGMII)
1748
1749 /*
1750  * Read a MII PHY register.
1751  *
1752  * Returns:
1753  *  0 on success
1754  */
1755 static int tsec_miiphy_read(char *devname, unsigned char addr,
1756                             unsigned char reg, unsigned short *value)
1757 {
1758         unsigned short ret;
1759         struct tsec_private *priv = privlist[0];
1760
1761         if (NULL == priv) {
1762                 printf("Can't read PHY at address %d\n", addr);
1763                 return -1;
1764         }
1765
1766         ret = (unsigned short)tsec_local_mdio_read(priv->phyregs, addr, reg);
1767         *value = ret;
1768
1769         return 0;
1770 }
1771
1772 /*
1773  * Write a MII PHY register.
1774  *
1775  * Returns:
1776  *  0 on success
1777  */
1778 static int tsec_miiphy_write(char *devname, unsigned char addr,
1779                              unsigned char reg, unsigned short value)
1780 {
1781         struct tsec_private *priv = privlist[0];
1782
1783         if (NULL == priv) {
1784                 printf("Can't write PHY at address %d\n", addr);
1785                 return -1;
1786         }
1787
1788         tsec_local_mdio_write(priv->phyregs, addr, reg, value);
1789
1790         return 0;
1791 }
1792
1793 #endif
1794
1795 #ifdef CONFIG_MCAST_TFTP
1796
1797 /* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
1798
1799 /* Set the appropriate hash bit for the given addr */
1800
1801 /* The algorithm works like so:
1802  * 1) Take the Destination Address (ie the multicast address), and
1803  * do a CRC on it (little endian), and reverse the bits of the
1804  * result.
1805  * 2) Use the 8 most significant bits as a hash into a 256-entry
1806  * table.  The table is controlled through 8 32-bit registers:
1807  * gaddr0-7.  gaddr0's MSB is entry 0, and gaddr7's LSB is
1808  * gaddr7.  This means that the 3 most significant bits in the
1809  * hash index which gaddr register to use, and the 5 other bits
1810  * indicate which bit (assuming an IBM numbering scheme, which
1811  * for PowerPC (tm) is usually the case) in the tregister holds
1812  * the entry. */
1813 static int
1814 tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)
1815 {
1816  struct tsec_private *priv = privlist[1];
1817  volatile tsec_t *regs = priv->regs;
1818  volatile u32  *reg_array, value;
1819  u8 result, whichbit, whichreg;
1820
1821         result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff);
1822         whichbit = result & 0x1f;       /* the 5 LSB = which bit to set */
1823         whichreg = result >> 5;         /* the 3 MSB = which reg to set it in */
1824         value = (1 << (31-whichbit));
1825
1826         reg_array = &(regs->hash.gaddr0);
1827
1828         if (set) {
1829                 reg_array[whichreg] |= value;
1830         } else {
1831                 reg_array[whichreg] &= ~value;
1832         }
1833         return 0;
1834 }
1835 #endif /* Multicast TFTP ? */