]> git.sur5r.net Git - u-boot/blob - drivers/qe/uec_phy.c
Merge branch 'fixes' into cleanups
[u-boot] / drivers / qe / uec_phy.c
1 /*
2  * Copyright (C) 2005 Freescale Semiconductor, Inc.
3  *
4  * Author: Shlomi Gridish
5  *
6  * Description: UCC GETH Driver -- PHY handling
7  *              Driver for UEC on QE
8  *              Based on 8260_io/fcc_enet.c
9  *
10  * This program is free software; you can redistribute  it and/or modify it
11  * under  the terms of  the GNU General  Public License as published by the
12  * Free Software Foundation;  either version 2 of the  License, or (at your
13  * option) any later version.
14  *
15  */
16
17 #include "common.h"
18 #include "net.h"
19 #include "malloc.h"
20 #include "asm/errno.h"
21 #include "asm/immap_qe.h"
22 #include "asm/io.h"
23 #include "qe.h"
24 #include "uccf.h"
25 #include "uec.h"
26 #include "uec_phy.h"
27 #include "miiphy.h"
28
29 #define ugphy_printk(format, arg...)  \
30         printf(format "\n", ## arg)
31
32 #define ugphy_dbg(format, arg...)            \
33         ugphy_printk(format , ## arg)
34 #define ugphy_err(format, arg...)            \
35         ugphy_printk(format , ## arg)
36 #define ugphy_info(format, arg...)           \
37         ugphy_printk(format , ## arg)
38 #define ugphy_warn(format, arg...)           \
39         ugphy_printk(format , ## arg)
40
41 #ifdef UEC_VERBOSE_DEBUG
42 #define ugphy_vdbg ugphy_dbg
43 #else
44 #define ugphy_vdbg(ugeth, fmt, args...) do { } while (0)
45 #endif /* UEC_VERBOSE_DEBUG */
46
47 /*--------------------------------------------------------------------+
48  * Fixed PHY (PHY-less) support for Ethernet Ports.
49  *
50  * Copied from cpu/ppc4xx/4xx_enet.c
51  *--------------------------------------------------------------------*/
52
53 /*
54  * Some boards do not have a PHY for each ethernet port. These ports
55  * are known as Fixed PHY (or PHY-less) ports. For such ports, set
56  * the appropriate CONFIG_PHY_ADDR equal to CONFIG_FIXED_PHY and
57  * then define CONFIG_SYS_FIXED_PHY_PORTS to define what the speed and
58  * duplex should be for these ports in the board configuration
59  * file.
60  *
61  * For Example:
62  *     #define CONFIG_FIXED_PHY   0xFFFFFFFF
63  *
64  *     #define CONFIG_PHY_ADDR    CONFIG_FIXED_PHY
65  *     #define CONFIG_PHY1_ADDR   1
66  *     #define CONFIG_PHY2_ADDR   CONFIG_FIXED_PHY
67  *     #define CONFIG_PHY3_ADDR   3
68  *
69  *     #define CONFIG_SYS_FIXED_PHY_PORT(devnum,speed,duplex) \
70  *                     {devnum, speed, duplex},
71  *
72  *     #define CONFIG_SYS_FIXED_PHY_PORTS \
73  *                     CONFIG_SYS_FIXED_PHY_PORT(0,SPEED_100,DUPLEX_FULL) \
74  *                     CONFIG_SYS_FIXED_PHY_PORT(2,SPEED_100,DUPLEX_HALF)
75  */
76
77 #ifndef CONFIG_FIXED_PHY
78 #define CONFIG_FIXED_PHY        0xFFFFFFFF /* Fixed PHY (PHY-less) */
79 #endif
80
81 #ifndef CONFIG_SYS_FIXED_PHY_PORTS
82 #define CONFIG_SYS_FIXED_PHY_PORTS      /* default is an empty array */
83 #endif
84
85 struct fixed_phy_port {
86         unsigned int devnum;    /* ethernet port */
87         unsigned int speed;     /* specified speed 10,100 or 1000 */
88         unsigned int duplex;    /* specified duplex FULL or HALF */
89 };
90
91 static const struct fixed_phy_port fixed_phy_port[] = {
92         CONFIG_SYS_FIXED_PHY_PORTS /* defined in board configuration file */
93 };
94
95 static void config_genmii_advert (struct uec_mii_info *mii_info);
96 static void genmii_setup_forced (struct uec_mii_info *mii_info);
97 static void genmii_restart_aneg (struct uec_mii_info *mii_info);
98 static int gbit_config_aneg (struct uec_mii_info *mii_info);
99 static int genmii_config_aneg (struct uec_mii_info *mii_info);
100 static int genmii_update_link (struct uec_mii_info *mii_info);
101 static int genmii_read_status (struct uec_mii_info *mii_info);
102 u16 phy_read (struct uec_mii_info *mii_info, u16 regnum);
103 void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val);
104
105 /* Write value to the PHY for this device to the register at regnum, */
106 /* waiting until the write is done before it returns.  All PHY */
107 /* configuration has to be done through the TSEC1 MIIM regs */
108 void uec_write_phy_reg (struct eth_device *dev, int mii_id, int regnum, int value)
109 {
110         uec_private_t *ugeth = (uec_private_t *) dev->priv;
111         uec_mii_t *ug_regs;
112         enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
113         u32 tmp_reg;
114
115         ug_regs = ugeth->uec_mii_regs;
116
117         /* Stop the MII management read cycle */
118         out_be32 (&ug_regs->miimcom, 0);
119         /* Setting up the MII Mangement Address Register */
120         tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
121         out_be32 (&ug_regs->miimadd, tmp_reg);
122
123         /* Setting up the MII Mangement Control Register with the value */
124         out_be32 (&ug_regs->miimcon, (u32) value);
125         sync();
126
127         /* Wait till MII management write is complete */
128         while ((in_be32 (&ug_regs->miimind)) & MIIMIND_BUSY);
129 }
130
131 /* Reads from register regnum in the PHY for device dev, */
132 /* returning the value.  Clears miimcom first.  All PHY */
133 /* configuration has to be done through the TSEC1 MIIM regs */
134 int uec_read_phy_reg (struct eth_device *dev, int mii_id, int regnum)
135 {
136         uec_private_t *ugeth = (uec_private_t *) dev->priv;
137         uec_mii_t *ug_regs;
138         enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
139         u32 tmp_reg;
140         u16 value;
141
142         ug_regs = ugeth->uec_mii_regs;
143
144         /* Setting up the MII Mangement Address Register */
145         tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
146         out_be32 (&ug_regs->miimadd, tmp_reg);
147
148         /* clear MII management command cycle */
149         out_be32 (&ug_regs->miimcom, 0);
150         sync();
151
152         /* Perform an MII management read cycle */
153         out_be32 (&ug_regs->miimcom, MIIMCOM_READ_CYCLE);
154
155         /* Wait till MII management write is complete */
156         while ((in_be32 (&ug_regs->miimind)) &
157                (MIIMIND_NOT_VALID | MIIMIND_BUSY));
158
159         /* Read MII management status  */
160         value = (u16) in_be32 (&ug_regs->miimstat);
161         if (value == 0xffff)
162                 ugphy_vdbg
163                         ("read wrong value : mii_id %d,mii_reg %d, base %08x",
164                          mii_id, mii_reg, (u32) & (ug_regs->miimcfg));
165
166         return (value);
167 }
168
169 void mii_clear_phy_interrupt (struct uec_mii_info *mii_info)
170 {
171         if (mii_info->phyinfo->ack_interrupt)
172                 mii_info->phyinfo->ack_interrupt (mii_info);
173 }
174
175 void mii_configure_phy_interrupt (struct uec_mii_info *mii_info,
176                                   u32 interrupts)
177 {
178         mii_info->interrupts = interrupts;
179         if (mii_info->phyinfo->config_intr)
180                 mii_info->phyinfo->config_intr (mii_info);
181 }
182
183 /* Writes MII_ADVERTISE with the appropriate values, after
184  * sanitizing advertise to make sure only supported features
185  * are advertised
186  */
187 static void config_genmii_advert (struct uec_mii_info *mii_info)
188 {
189         u32 advertise;
190         u16 adv;
191
192         /* Only allow advertising what this PHY supports */
193         mii_info->advertising &= mii_info->phyinfo->features;
194         advertise = mii_info->advertising;
195
196         /* Setup standard advertisement */
197         adv = phy_read (mii_info, PHY_ANAR);
198         adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
199         if (advertise & ADVERTISED_10baseT_Half)
200                 adv |= ADVERTISE_10HALF;
201         if (advertise & ADVERTISED_10baseT_Full)
202                 adv |= ADVERTISE_10FULL;
203         if (advertise & ADVERTISED_100baseT_Half)
204                 adv |= ADVERTISE_100HALF;
205         if (advertise & ADVERTISED_100baseT_Full)
206                 adv |= ADVERTISE_100FULL;
207         phy_write (mii_info, PHY_ANAR, adv);
208 }
209
210 static void genmii_setup_forced (struct uec_mii_info *mii_info)
211 {
212         u16 ctrl;
213         u32 features = mii_info->phyinfo->features;
214
215         ctrl = phy_read (mii_info, PHY_BMCR);
216
217         ctrl &= ~(PHY_BMCR_DPLX | PHY_BMCR_100_MBPS |
218                   PHY_BMCR_1000_MBPS | PHY_BMCR_AUTON);
219         ctrl |= PHY_BMCR_RESET;
220
221         switch (mii_info->speed) {
222         case SPEED_1000:
223                 if (features & (SUPPORTED_1000baseT_Half
224                                 | SUPPORTED_1000baseT_Full)) {
225                         ctrl |= PHY_BMCR_1000_MBPS;
226                         break;
227                 }
228                 mii_info->speed = SPEED_100;
229         case SPEED_100:
230                 if (features & (SUPPORTED_100baseT_Half
231                                 | SUPPORTED_100baseT_Full)) {
232                         ctrl |= PHY_BMCR_100_MBPS;
233                         break;
234                 }
235                 mii_info->speed = SPEED_10;
236         case SPEED_10:
237                 if (features & (SUPPORTED_10baseT_Half
238                                 | SUPPORTED_10baseT_Full))
239                         break;
240         default:                /* Unsupported speed! */
241                 ugphy_err ("%s: Bad speed!", mii_info->dev->name);
242                 break;
243         }
244
245         phy_write (mii_info, PHY_BMCR, ctrl);
246 }
247
248 /* Enable and Restart Autonegotiation */
249 static void genmii_restart_aneg (struct uec_mii_info *mii_info)
250 {
251         u16 ctl;
252
253         ctl = phy_read (mii_info, PHY_BMCR);
254         ctl |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
255         phy_write (mii_info, PHY_BMCR, ctl);
256 }
257
258 static int gbit_config_aneg (struct uec_mii_info *mii_info)
259 {
260         u16 adv;
261         u32 advertise;
262
263         if (mii_info->autoneg) {
264                 /* Configure the ADVERTISE register */
265                 config_genmii_advert (mii_info);
266                 advertise = mii_info->advertising;
267
268                 adv = phy_read (mii_info, MII_1000BASETCONTROL);
269                 adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
270                          MII_1000BASETCONTROL_HALFDUPLEXCAP);
271                 if (advertise & SUPPORTED_1000baseT_Half)
272                         adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
273                 if (advertise & SUPPORTED_1000baseT_Full)
274                         adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
275                 phy_write (mii_info, MII_1000BASETCONTROL, adv);
276
277                 /* Start/Restart aneg */
278                 genmii_restart_aneg (mii_info);
279         } else
280                 genmii_setup_forced (mii_info);
281
282         return 0;
283 }
284
285 static int marvell_config_aneg (struct uec_mii_info *mii_info)
286 {
287         /* The Marvell PHY has an errata which requires
288          * that certain registers get written in order
289          * to restart autonegotiation */
290         phy_write (mii_info, PHY_BMCR, PHY_BMCR_RESET);
291
292         phy_write (mii_info, 0x1d, 0x1f);
293         phy_write (mii_info, 0x1e, 0x200c);
294         phy_write (mii_info, 0x1d, 0x5);
295         phy_write (mii_info, 0x1e, 0);
296         phy_write (mii_info, 0x1e, 0x100);
297
298         gbit_config_aneg (mii_info);
299
300         return 0;
301 }
302
303 static int genmii_config_aneg (struct uec_mii_info *mii_info)
304 {
305         if (mii_info->autoneg) {
306                 config_genmii_advert (mii_info);
307                 genmii_restart_aneg (mii_info);
308         } else
309                 genmii_setup_forced (mii_info);
310
311         return 0;
312 }
313
314 static int genmii_update_link (struct uec_mii_info *mii_info)
315 {
316         u16 status;
317
318         /* Status is read once to clear old link state */
319         phy_read (mii_info, PHY_BMSR);
320
321         /*
322          * Wait if the link is up, and autonegotiation is in progress
323          * (ie - we're capable and it's not done)
324          */
325         status = phy_read(mii_info, PHY_BMSR);
326         if ((status & PHY_BMSR_LS) && (status & PHY_BMSR_AUTN_ABLE)
327             && !(status & PHY_BMSR_AUTN_COMP)) {
328                 int i = 0;
329
330                 while (!(status & PHY_BMSR_AUTN_COMP)) {
331                         /*
332                          * Timeout reached ?
333                          */
334                         if (i > UGETH_AN_TIMEOUT) {
335                                 mii_info->link = 0;
336                                 return 0;
337                         }
338
339                         i++;
340                         udelay(1000);   /* 1 ms */
341                         status = phy_read(mii_info, PHY_BMSR);
342                 }
343                 mii_info->link = 1;
344                 udelay(500000); /* another 500 ms (results in faster booting) */
345         } else {
346                 if (status & PHY_BMSR_LS)
347                         mii_info->link = 1;
348                 else
349                         mii_info->link = 0;
350         }
351
352         return 0;
353 }
354
355 static int genmii_read_status (struct uec_mii_info *mii_info)
356 {
357         u16 status;
358         int err;
359
360         /* Update the link, but return if there
361          * was an error */
362         err = genmii_update_link (mii_info);
363         if (err)
364                 return err;
365
366         if (mii_info->autoneg) {
367                 status = phy_read(mii_info, MII_1000BASETSTATUS);
368
369                 if (status & (LPA_1000FULL | LPA_1000HALF)) {
370                         mii_info->speed = SPEED_1000;
371                         if (status & LPA_1000FULL)
372                                 mii_info->duplex = DUPLEX_FULL;
373                         else
374                                 mii_info->duplex = DUPLEX_HALF;
375                 } else {
376                         status = phy_read(mii_info, PHY_ANLPAR);
377
378                         if (status & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD))
379                                 mii_info->duplex = DUPLEX_FULL;
380                         else
381                                 mii_info->duplex = DUPLEX_HALF;
382                         if (status & (PHY_ANLPAR_TXFD | PHY_ANLPAR_TX))
383                                 mii_info->speed = SPEED_100;
384                         else
385                                 mii_info->speed = SPEED_10;
386                 }
387                 mii_info->pause = 0;
388         }
389         /* On non-aneg, we assume what we put in BMCR is the speed,
390          * though magic-aneg shouldn't prevent this case from occurring
391          */
392
393         return 0;
394 }
395
396 static int bcm_init(struct uec_mii_info *mii_info)
397 {
398         struct eth_device *edev = mii_info->dev;
399         uec_private_t *uec = edev->priv;
400
401         gbit_config_aneg(mii_info);
402
403         if (uec->uec_info->enet_interface == ENET_1000_RGMII_RXID) {
404                 u16 val;
405                 int cnt = 50;
406
407                 /* Wait for aneg to complete. */
408                 do
409                         val = phy_read(mii_info, PHY_BMSR);
410                 while (--cnt && !(val & PHY_BMSR_AUTN_COMP));
411
412                 /* Set RDX clk delay. */
413                 phy_write(mii_info, 0x18, 0x7 | (7 << 12));
414
415                 val = phy_read(mii_info, 0x18);
416                 /* Set RDX-RXC skew. */
417                 val |= (1 << 8);
418                 val |= (7 | (7 << 12));
419                 /* Write bits 14:0. */
420                 val |= (1 << 15);
421                 phy_write(mii_info, 0x18, val);
422         }
423
424          return 0;
425 }
426
427 static int marvell_init(struct uec_mii_info *mii_info)
428 {
429         struct eth_device *edev = mii_info->dev;
430         uec_private_t *uec = edev->priv;
431
432         if (uec->uec_info->enet_interface == ENET_1000_RGMII_ID) {
433                 int temp;
434
435                 temp = phy_read(mii_info, MII_M1111_PHY_EXT_CR);
436                 temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
437                 phy_write(mii_info, MII_M1111_PHY_EXT_CR, temp);
438
439                 temp = phy_read(mii_info, MII_M1111_PHY_EXT_SR);
440                 temp &= ~MII_M1111_HWCFG_MODE_MASK;
441                 temp |= MII_M1111_HWCFG_MODE_RGMII;
442                 phy_write(mii_info, MII_M1111_PHY_EXT_SR, temp);
443
444                 phy_write(mii_info, PHY_BMCR, PHY_BMCR_RESET);
445         }
446
447         return 0;
448 }
449
450 static int marvell_read_status (struct uec_mii_info *mii_info)
451 {
452         u16 status;
453         int err;
454
455         /* Update the link, but return if there
456          * was an error */
457         err = genmii_update_link (mii_info);
458         if (err)
459                 return err;
460
461         /* If the link is up, read the speed and duplex */
462         /* If we aren't autonegotiating, assume speeds
463          * are as set */
464         if (mii_info->autoneg && mii_info->link) {
465                 int speed;
466
467                 status = phy_read (mii_info, MII_M1011_PHY_SPEC_STATUS);
468
469                 /* Get the duplexity */
470                 if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
471                         mii_info->duplex = DUPLEX_FULL;
472                 else
473                         mii_info->duplex = DUPLEX_HALF;
474
475                 /* Get the speed */
476                 speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
477                 switch (speed) {
478                 case MII_M1011_PHY_SPEC_STATUS_1000:
479                         mii_info->speed = SPEED_1000;
480                         break;
481                 case MII_M1011_PHY_SPEC_STATUS_100:
482                         mii_info->speed = SPEED_100;
483                         break;
484                 default:
485                         mii_info->speed = SPEED_10;
486                         break;
487                 }
488                 mii_info->pause = 0;
489         }
490
491         return 0;
492 }
493
494 static int marvell_ack_interrupt (struct uec_mii_info *mii_info)
495 {
496         /* Clear the interrupts by reading the reg */
497         phy_read (mii_info, MII_M1011_IEVENT);
498
499         return 0;
500 }
501
502 static int marvell_config_intr (struct uec_mii_info *mii_info)
503 {
504         if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
505                 phy_write (mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
506         else
507                 phy_write (mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
508
509         return 0;
510 }
511
512 static int dm9161_init (struct uec_mii_info *mii_info)
513 {
514         /* Reset the PHY */
515         phy_write (mii_info, PHY_BMCR, phy_read (mii_info, PHY_BMCR) |
516                    PHY_BMCR_RESET);
517         /* PHY and MAC connect */
518         phy_write (mii_info, PHY_BMCR, phy_read (mii_info, PHY_BMCR) &
519                    ~PHY_BMCR_ISO);
520
521         phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
522
523         config_genmii_advert (mii_info);
524         /* Start/restart aneg */
525         genmii_config_aneg (mii_info);
526
527         return 0;
528 }
529
530 static int dm9161_config_aneg (struct uec_mii_info *mii_info)
531 {
532         return 0;
533 }
534
535 static int dm9161_read_status (struct uec_mii_info *mii_info)
536 {
537         u16 status;
538         int err;
539
540         /* Update the link, but return if there was an error */
541         err = genmii_update_link (mii_info);
542         if (err)
543                 return err;
544         /* If the link is up, read the speed and duplex
545            If we aren't autonegotiating assume speeds are as set */
546         if (mii_info->autoneg && mii_info->link) {
547                 status = phy_read (mii_info, MII_DM9161_SCSR);
548                 if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
549                         mii_info->speed = SPEED_100;
550                 else
551                         mii_info->speed = SPEED_10;
552
553                 if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
554                         mii_info->duplex = DUPLEX_FULL;
555                 else
556                         mii_info->duplex = DUPLEX_HALF;
557         }
558
559         return 0;
560 }
561
562 static int dm9161_ack_interrupt (struct uec_mii_info *mii_info)
563 {
564         /* Clear the interrupt by reading the reg */
565         phy_read (mii_info, MII_DM9161_INTR);
566
567         return 0;
568 }
569
570 static int dm9161_config_intr (struct uec_mii_info *mii_info)
571 {
572         if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
573                 phy_write (mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
574         else
575                 phy_write (mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
576
577         return 0;
578 }
579
580 static void dm9161_close (struct uec_mii_info *mii_info)
581 {
582 }
583
584 static int fixed_phy_aneg (struct uec_mii_info *mii_info)
585 {
586         mii_info->autoneg = 0; /* Turn off auto negotiation for fixed phy */
587         return 0;
588 }
589
590 static int fixed_phy_read_status (struct uec_mii_info *mii_info)
591 {
592         int i = 0;
593
594         for (i = 0; i < ARRAY_SIZE(fixed_phy_port); i++) {
595                 if (mii_info->mii_id == fixed_phy_port[i].devnum) {
596                         mii_info->speed = fixed_phy_port[i].speed;
597                         mii_info->duplex = fixed_phy_port[i].duplex;
598                         mii_info->link = 1; /* Link is always UP */
599                         mii_info->pause = 0;
600                         break;
601                 }
602         }
603         return 0;
604 }
605
606 static struct phy_info phy_info_dm9161 = {
607         .phy_id = 0x0181b880,
608         .phy_id_mask = 0x0ffffff0,
609         .name = "Davicom DM9161E",
610         .init = dm9161_init,
611         .config_aneg = dm9161_config_aneg,
612         .read_status = dm9161_read_status,
613         .close = dm9161_close,
614 };
615
616 static struct phy_info phy_info_dm9161a = {
617         .phy_id = 0x0181b8a0,
618         .phy_id_mask = 0x0ffffff0,
619         .name = "Davicom DM9161A",
620         .features = MII_BASIC_FEATURES,
621         .init = dm9161_init,
622         .config_aneg = dm9161_config_aneg,
623         .read_status = dm9161_read_status,
624         .ack_interrupt = dm9161_ack_interrupt,
625         .config_intr = dm9161_config_intr,
626         .close = dm9161_close,
627 };
628
629 static struct phy_info phy_info_marvell = {
630         .phy_id = 0x01410c00,
631         .phy_id_mask = 0xffffff00,
632         .name = "Marvell 88E11x1",
633         .features = MII_GBIT_FEATURES,
634         .init = &marvell_init,
635         .config_aneg = &marvell_config_aneg,
636         .read_status = &marvell_read_status,
637         .ack_interrupt = &marvell_ack_interrupt,
638         .config_intr = &marvell_config_intr,
639 };
640
641 static struct phy_info phy_info_bcm5481 = {
642         .phy_id = 0x0143bca0,
643         .phy_id_mask = 0xffffff0,
644         .name = "Broadcom 5481",
645         .features = MII_GBIT_FEATURES,
646         .read_status = genmii_read_status,
647         .init = bcm_init,
648 };
649
650 static struct phy_info phy_info_fixedphy = {
651         .phy_id = CONFIG_FIXED_PHY,
652         .phy_id_mask = CONFIG_FIXED_PHY,
653         .name = "Fixed PHY",
654         .config_aneg = fixed_phy_aneg,
655         .read_status = fixed_phy_read_status,
656 };
657
658 static struct phy_info phy_info_genmii = {
659         .phy_id = 0x00000000,
660         .phy_id_mask = 0x00000000,
661         .name = "Generic MII",
662         .features = MII_BASIC_FEATURES,
663         .config_aneg = genmii_config_aneg,
664         .read_status = genmii_read_status,
665 };
666
667 static struct phy_info *phy_info[] = {
668         &phy_info_dm9161,
669         &phy_info_dm9161a,
670         &phy_info_marvell,
671         &phy_info_bcm5481,
672         &phy_info_fixedphy,
673         &phy_info_genmii,
674         NULL
675 };
676
677 u16 phy_read (struct uec_mii_info *mii_info, u16 regnum)
678 {
679         return mii_info->mdio_read (mii_info->dev, mii_info->mii_id, regnum);
680 }
681
682 void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val)
683 {
684         mii_info->mdio_write (mii_info->dev, mii_info->mii_id, regnum, val);
685 }
686
687 /* Use the PHY ID registers to determine what type of PHY is attached
688  * to device dev.  return a struct phy_info structure describing that PHY
689  */
690 struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info)
691 {
692         u16 phy_reg;
693         u32 phy_ID;
694         int i;
695         struct phy_info *theInfo = NULL;
696
697         /* Grab the bits from PHYIR1, and put them in the upper half */
698         phy_reg = phy_read (mii_info, PHY_PHYIDR1);
699         phy_ID = (phy_reg & 0xffff) << 16;
700
701         /* Grab the bits from PHYIR2, and put them in the lower half */
702         phy_reg = phy_read (mii_info, PHY_PHYIDR2);
703         phy_ID |= (phy_reg & 0xffff);
704
705         /* loop through all the known PHY types, and find one that */
706         /* matches the ID we read from the PHY. */
707         for (i = 0; phy_info[i]; i++)
708                 if (phy_info[i]->phy_id ==
709                     (phy_ID & phy_info[i]->phy_id_mask)) {
710                         theInfo = phy_info[i];
711                         break;
712                 }
713
714         /* This shouldn't happen, as we have generic PHY support */
715         if (theInfo == NULL) {
716                 ugphy_info ("UEC: PHY id %x is not supported!", phy_ID);
717                 return NULL;
718         } else {
719                 ugphy_info ("UEC: PHY is %s (%x)", theInfo->name, phy_ID);
720         }
721
722         return theInfo;
723 }
724
725 void marvell_phy_interface_mode (struct eth_device *dev,
726                                  enet_interface_e mode)
727 {
728         uec_private_t *uec = (uec_private_t *) dev->priv;
729         struct uec_mii_info *mii_info;
730         u16 status;
731
732         if (!uec->mii_info) {
733                 printf ("%s: the PHY not initialized\n", __FUNCTION__);
734                 return;
735         }
736         mii_info = uec->mii_info;
737
738         if (mode == ENET_100_RGMII) {
739                 phy_write (mii_info, 0x00, 0x9140);
740                 phy_write (mii_info, 0x1d, 0x001f);
741                 phy_write (mii_info, 0x1e, 0x200c);
742                 phy_write (mii_info, 0x1d, 0x0005);
743                 phy_write (mii_info, 0x1e, 0x0000);
744                 phy_write (mii_info, 0x1e, 0x0100);
745                 phy_write (mii_info, 0x09, 0x0e00);
746                 phy_write (mii_info, 0x04, 0x01e1);
747                 phy_write (mii_info, 0x00, 0x9140);
748                 phy_write (mii_info, 0x00, 0x1000);
749                 udelay (100000);
750                 phy_write (mii_info, 0x00, 0x2900);
751                 phy_write (mii_info, 0x14, 0x0cd2);
752                 phy_write (mii_info, 0x00, 0xa100);
753                 phy_write (mii_info, 0x09, 0x0000);
754                 phy_write (mii_info, 0x1b, 0x800b);
755                 phy_write (mii_info, 0x04, 0x05e1);
756                 phy_write (mii_info, 0x00, 0xa100);
757                 phy_write (mii_info, 0x00, 0x2100);
758                 udelay (1000000);
759         } else if (mode == ENET_10_RGMII) {
760                 phy_write (mii_info, 0x14, 0x8e40);
761                 phy_write (mii_info, 0x1b, 0x800b);
762                 phy_write (mii_info, 0x14, 0x0c82);
763                 phy_write (mii_info, 0x00, 0x8100);
764                 udelay (1000000);
765         }
766
767         /* handle 88e1111 rev.B2 erratum 5.6 */
768         if (mii_info->autoneg) {
769                 status = phy_read (mii_info, PHY_BMCR);
770                 phy_write (mii_info, PHY_BMCR, status | PHY_BMCR_AUTON);
771         }
772         /* now the B2 will correctly report autoneg completion status */
773 }
774
775 void change_phy_interface_mode (struct eth_device *dev, enet_interface_e mode)
776 {
777 #ifdef CONFIG_PHY_MODE_NEED_CHANGE
778         marvell_phy_interface_mode (dev, mode);
779 #endif
780 }