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