vserver 2.0 rc7
[linux-2.6.git] / drivers / net / sungem_phy.c
1 /*
2  * PHY drivers for the sungem ethernet driver.
3  * 
4  * This file could be shared with other drivers.
5  * 
6  * (c) 2002, Benjamin Herrenscmidt (benh@kernel.crashing.org)
7  *
8  * TODO:
9  *  - Implement WOL
10  *  - Add support for PHYs that provide an IRQ line
11  *  - Eventually moved the entire polling state machine in
12  *    there (out of the eth driver), so that it can easily be
13  *    skipped on PHYs that implement it in hardware.
14  *  - On LXT971 & BCM5201, Apple uses some chip specific regs
15  *    to read the link status. Figure out why and if it makes
16  *    sense to do the same (magic aneg ?)
17  *  - Apple has some additional power management code for some
18  *    Broadcom PHYs that they "hide" from the OpenSource version
19  *    of darwin, still need to reverse engineer that
20  */
21
22 #include <linux/config.h>
23
24 #include <linux/module.h>
25
26 #include <linux/kernel.h>
27 #include <linux/sched.h>
28 #include <linux/types.h>
29 #include <linux/netdevice.h>
30 #include <linux/etherdevice.h>
31 #include <linux/mii.h>
32 #include <linux/ethtool.h>
33 #include <linux/delay.h>
34
35 #include "sungem_phy.h"
36
37 /* Link modes of the BCM5400 PHY */
38 static int phy_BCM5400_link_table[8][3] = {
39         { 0, 0, 0 },    /* No link */
40         { 0, 0, 0 },    /* 10BT Half Duplex */
41         { 1, 0, 0 },    /* 10BT Full Duplex */
42         { 0, 1, 0 },    /* 100BT Half Duplex */
43         { 0, 1, 0 },    /* 100BT Half Duplex */
44         { 1, 1, 0 },    /* 100BT Full Duplex*/
45         { 1, 0, 1 },    /* 1000BT */
46         { 1, 0, 1 },    /* 1000BT */
47 };
48
49 static inline int __phy_read(struct mii_phy* phy, int id, int reg)
50 {
51         return phy->mdio_read(phy->dev, id, reg);
52 }
53
54 static inline void __phy_write(struct mii_phy* phy, int id, int reg, int val)
55 {
56         phy->mdio_write(phy->dev, id, reg, val);
57 }
58
59 static inline int phy_read(struct mii_phy* phy, int reg)
60 {
61         return phy->mdio_read(phy->dev, phy->mii_id, reg);
62 }
63
64 static inline void phy_write(struct mii_phy* phy, int reg, int val)
65 {
66         phy->mdio_write(phy->dev, phy->mii_id, reg, val);
67 }
68
69 static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
70 {
71         u16 val;
72         int limit = 10000;
73         
74         val = __phy_read(phy, phy_id, MII_BMCR);
75         val &= ~(BMCR_ISOLATE | BMCR_PDOWN);
76         val |= BMCR_RESET;
77         __phy_write(phy, phy_id, MII_BMCR, val);
78
79         udelay(100);
80
81         while (limit--) {
82                 val = __phy_read(phy, phy_id, MII_BMCR);
83                 if ((val & BMCR_RESET) == 0)
84                         break;
85                 udelay(10);
86         }
87         if ((val & BMCR_ISOLATE) && limit > 0)
88                 __phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
89         
90         return (limit <= 0);
91 }
92
93 static int bcm5201_init(struct mii_phy* phy)
94 {
95         u16 data;
96
97         data = phy_read(phy, MII_BCM5201_MULTIPHY);
98         data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
99         phy_write(phy, MII_BCM5201_MULTIPHY, data);
100
101         phy_write(phy, MII_BCM5201_INTERRUPT, 0);
102
103         return 0;
104 }
105
106 static int bcm5201_suspend(struct mii_phy* phy)
107 {
108         phy_write(phy, MII_BCM5201_INTERRUPT, 0);
109         phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
110
111         return 0;
112 }
113
114 static int bcm5221_init(struct mii_phy* phy)
115 {
116         u16 data;
117
118         data = phy_read(phy, MII_BCM5221_TEST);
119         phy_write(phy, MII_BCM5221_TEST,
120                 data | MII_BCM5221_TEST_ENABLE_SHADOWS);
121
122         data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
123         phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
124                 data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
125
126         data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
127         phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
128                 data | MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR);
129
130         data = phy_read(phy, MII_BCM5221_TEST);
131         phy_write(phy, MII_BCM5221_TEST,
132                 data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
133
134         return 0;
135 }
136
137 static int bcm5221_suspend(struct mii_phy* phy)
138 {
139         u16 data;
140
141         data = phy_read(phy, MII_BCM5221_TEST);
142         phy_write(phy, MII_BCM5221_TEST,
143                 data | MII_BCM5221_TEST_ENABLE_SHADOWS);
144
145         data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
146         phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
147                   data | MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE);
148
149         return 0;
150 }
151
152 static int bcm5400_init(struct mii_phy* phy)
153 {
154         u16 data;
155
156         /* Configure for gigabit full duplex */
157         data = phy_read(phy, MII_BCM5400_AUXCONTROL);
158         data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
159         phy_write(phy, MII_BCM5400_AUXCONTROL, data);
160         
161         data = phy_read(phy, MII_BCM5400_GB_CONTROL);
162         data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
163         phy_write(phy, MII_BCM5400_GB_CONTROL, data);
164         
165         udelay(100);
166
167         /* Reset and configure cascaded 10/100 PHY */
168         (void)reset_one_mii_phy(phy, 0x1f);
169         
170         data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
171         data |= MII_BCM5201_MULTIPHY_SERIALMODE;
172         __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
173
174         data = phy_read(phy, MII_BCM5400_AUXCONTROL);
175         data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
176         phy_write(phy, MII_BCM5400_AUXCONTROL, data);
177
178         return 0;
179 }
180
181 static int bcm5400_suspend(struct mii_phy* phy)
182 {
183 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
184         phy_write(phy, MII_BMCR, BMCR_PDOWN);
185 #endif
186         return 0;
187 }
188
189 static int bcm5401_init(struct mii_phy* phy)
190 {
191         u16 data;
192         int rev;
193
194         rev = phy_read(phy, MII_PHYSID2) & 0x000f;
195         if (rev == 0 || rev == 3) {
196                 /* Some revisions of 5401 appear to need this
197                  * initialisation sequence to disable, according
198                  * to OF, "tap power management"
199                  * 
200                  * WARNING ! OF and Darwin don't agree on the
201                  * register addresses. OF seem to interpret the
202                  * register numbers below as decimal
203                  *
204                  * Note: This should (and does) match tg3_init_5401phy_dsp
205                  *       in the tg3.c driver. -DaveM
206                  */
207                 phy_write(phy, 0x18, 0x0c20);
208                 phy_write(phy, 0x17, 0x0012);
209                 phy_write(phy, 0x15, 0x1804);
210                 phy_write(phy, 0x17, 0x0013);
211                 phy_write(phy, 0x15, 0x1204);
212                 phy_write(phy, 0x17, 0x8006);
213                 phy_write(phy, 0x15, 0x0132);
214                 phy_write(phy, 0x17, 0x8006);
215                 phy_write(phy, 0x15, 0x0232);
216                 phy_write(phy, 0x17, 0x201f);
217                 phy_write(phy, 0x15, 0x0a20);
218         }
219         
220         /* Configure for gigabit full duplex */
221         data = phy_read(phy, MII_BCM5400_GB_CONTROL);
222         data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
223         phy_write(phy, MII_BCM5400_GB_CONTROL, data);
224
225         udelay(10);
226
227         /* Reset and configure cascaded 10/100 PHY */
228         (void)reset_one_mii_phy(phy, 0x1f);
229         
230         data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
231         data |= MII_BCM5201_MULTIPHY_SERIALMODE;
232         __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
233
234         return 0;
235 }
236
237 static int bcm5401_suspend(struct mii_phy* phy)
238 {
239 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
240         phy_write(phy, MII_BMCR, BMCR_PDOWN);
241 #endif
242         return 0;
243 }
244
245 static int bcm5411_init(struct mii_phy* phy)
246 {
247         u16 data;
248
249         /* Here's some more Apple black magic to setup
250          * some voltage stuffs.
251          */
252         phy_write(phy, 0x1c, 0x8c23);
253         phy_write(phy, 0x1c, 0x8ca3);
254         phy_write(phy, 0x1c, 0x8c23);
255
256         /* Here, Apple seems to want to reset it, do
257          * it as well
258          */
259         phy_write(phy, MII_BMCR, BMCR_RESET);
260         phy_write(phy, MII_BMCR, 0x1340);
261
262         data = phy_read(phy, MII_BCM5400_GB_CONTROL);
263         data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
264         phy_write(phy, MII_BCM5400_GB_CONTROL, data);
265
266         udelay(10);
267
268         /* Reset and configure cascaded 10/100 PHY */
269         (void)reset_one_mii_phy(phy, 0x1f);
270         
271         return 0;
272 }
273
274 static int bcm5411_suspend(struct mii_phy* phy)
275 {
276         phy_write(phy, MII_BMCR, BMCR_PDOWN);
277
278         return 0;
279 }
280
281 static int bcm5421_init(struct mii_phy* phy)
282 {
283         u16 data;
284         int rev;
285
286         rev = phy_read(phy, MII_PHYSID2) & 0x000f;
287         if (rev == 0) {
288                 /* This is borrowed from MacOS
289                  */
290                 phy_write(phy, 0x18, 0x1007);
291                 data = phy_read(phy, 0x18);
292                 phy_write(phy, 0x18, data | 0x0400);
293                 phy_write(phy, 0x18, 0x0007);
294                 data = phy_read(phy, 0x18);
295                 phy_write(phy, 0x18, data | 0x0800);
296                 phy_write(phy, 0x17, 0x000a);
297                 data = phy_read(phy, 0x15);
298                 phy_write(phy, 0x15, data | 0x0200);
299         }
300 #if 0
301         /* This has to be verified before I enable it */
302         /* Enable automatic low-power */
303         phy_write(phy, 0x1c, 0x9002);
304         phy_write(phy, 0x1c, 0xa821);
305         phy_write(phy, 0x1c, 0x941d);
306 #endif
307         return 0;
308 }
309
310 static int bcm5421k2_init(struct mii_phy* phy)
311 {
312         /* Init code borrowed from OF */
313         phy_write(phy, 4, 0x01e1);
314         phy_write(phy, 9, 0x0300);
315
316         return 0;
317 }
318
319 static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
320 {
321         u16 ctl, adv;
322         
323         phy->autoneg = 1;
324         phy->speed = SPEED_10;
325         phy->duplex = DUPLEX_HALF;
326         phy->pause = 0;
327         phy->advertising = advertise;
328
329         /* Setup standard advertise */
330         adv = phy_read(phy, MII_ADVERTISE);
331         adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
332         if (advertise & ADVERTISED_10baseT_Half)
333                 adv |= ADVERTISE_10HALF;
334         if (advertise & ADVERTISED_10baseT_Full)
335                 adv |= ADVERTISE_10FULL;
336         if (advertise & ADVERTISED_100baseT_Half)
337                 adv |= ADVERTISE_100HALF;
338         if (advertise & ADVERTISED_100baseT_Full)
339                 adv |= ADVERTISE_100FULL;
340         phy_write(phy, MII_ADVERTISE, adv);
341
342         /* Setup 1000BT advertise */
343         adv = phy_read(phy, MII_1000BASETCONTROL);
344         adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP);
345         if (advertise & SUPPORTED_1000baseT_Half)
346                 adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
347         if (advertise & SUPPORTED_1000baseT_Full)
348                 adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
349         phy_write(phy, MII_1000BASETCONTROL, adv);
350
351         /* Start/Restart aneg */
352         ctl = phy_read(phy, MII_BMCR);
353         ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
354         phy_write(phy, MII_BMCR, ctl);
355
356         return 0;
357 }
358
359 static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
360 {
361         u16 ctl;
362         
363         phy->autoneg = 0;
364         phy->speed = speed;
365         phy->duplex = fd;
366         phy->pause = 0;
367
368         ctl = phy_read(phy, MII_BMCR);
369         ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
370
371         /* First reset the PHY */
372         phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
373
374         /* Select speed & duplex */
375         switch(speed) {
376         case SPEED_10:
377                 break;
378         case SPEED_100:
379                 ctl |= BMCR_SPEED100;
380                 break;
381         case SPEED_1000:
382                 ctl |= BMCR_SPD2;
383         }
384         if (fd == DUPLEX_FULL)
385                 ctl |= BMCR_FULLDPLX;
386
387         // XXX Should we set the sungem to GII now on 1000BT ?
388         
389         phy_write(phy, MII_BMCR, ctl);
390
391         return 0;
392 }
393
394 static int bcm54xx_read_link(struct mii_phy *phy)
395 {
396         int link_mode;  
397         u16 val;
398         
399         if (phy->autoneg) {
400                 val = phy_read(phy, MII_BCM5400_AUXSTATUS);
401                 link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
402                              MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
403                 phy->duplex = phy_BCM5400_link_table[link_mode][0] ? DUPLEX_FULL : DUPLEX_HALF;
404                 phy->speed = phy_BCM5400_link_table[link_mode][2] ?
405                                 SPEED_1000 :
406                                 (phy_BCM5400_link_table[link_mode][1] ? SPEED_100 : SPEED_10);
407                 val = phy_read(phy, MII_LPA);
408                 phy->pause = ((val & LPA_PAUSE) != 0);
409         }
410         /* On non-aneg, we assume what we put in BMCR is the speed,
411          * though magic-aneg shouldn't prevent this case from occurring
412          */
413
414         return 0;
415 }
416
417 static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
418 {
419         u16 ctl, adv;
420         
421         phy->autoneg = 1;
422         phy->speed = SPEED_10;
423         phy->duplex = DUPLEX_HALF;
424         phy->pause = 0;
425         phy->advertising = advertise;
426
427         /* Setup standard advertise */
428         adv = phy_read(phy, MII_ADVERTISE);
429         adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
430         if (advertise & ADVERTISED_10baseT_Half)
431                 adv |= ADVERTISE_10HALF;
432         if (advertise & ADVERTISED_10baseT_Full)
433                 adv |= ADVERTISE_10FULL;
434         if (advertise & ADVERTISED_100baseT_Half)
435                 adv |= ADVERTISE_100HALF;
436         if (advertise & ADVERTISED_100baseT_Full)
437                 adv |= ADVERTISE_100FULL;
438         phy_write(phy, MII_ADVERTISE, adv);
439
440         /* Setup 1000BT advertise & enable crossover detect
441          * XXX How do we advertise 1000BT ? Darwin source is
442          * confusing here, they read from specific control and
443          * write to control... Someone has specs for those
444          * beasts ?
445          */
446         adv = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
447         adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX;
448         adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
449                         MII_1000BASETCONTROL_HALFDUPLEXCAP);
450         if (advertise & SUPPORTED_1000baseT_Half)
451                 adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
452         if (advertise & SUPPORTED_1000baseT_Full)
453                 adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
454         phy_write(phy, MII_1000BASETCONTROL, adv);
455
456         /* Start/Restart aneg */
457         ctl = phy_read(phy, MII_BMCR);
458         ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
459         phy_write(phy, MII_BMCR, ctl);
460
461         return 0;
462 }
463
464 static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
465 {
466         u16 ctl, ctl2;
467         
468         phy->autoneg = 0;
469         phy->speed = speed;
470         phy->duplex = fd;
471         phy->pause = 0;
472
473         ctl = phy_read(phy, MII_BMCR);
474         ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
475         ctl |= BMCR_RESET;
476
477         /* Select speed & duplex */
478         switch(speed) {
479         case SPEED_10:
480                 break;
481         case SPEED_100:
482                 ctl |= BMCR_SPEED100;
483                 break;
484         /* I'm not sure about the one below, again, Darwin source is
485          * quite confusing and I lack chip specs
486          */
487         case SPEED_1000:
488                 ctl |= BMCR_SPD2;
489         }
490         if (fd == DUPLEX_FULL)
491                 ctl |= BMCR_FULLDPLX;
492
493         /* Disable crossover. Again, the way Apple does it is strange,
494          * though I don't assume they are wrong ;)
495          */
496         ctl2 = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
497         ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX |
498                 MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX |
499                 MII_1000BASETCONTROL_FULLDUPLEXCAP |
500                 MII_1000BASETCONTROL_HALFDUPLEXCAP);
501         if (speed == SPEED_1000)
502                 ctl2 |= (fd == DUPLEX_FULL) ?
503                         MII_1000BASETCONTROL_FULLDUPLEXCAP :
504                         MII_1000BASETCONTROL_HALFDUPLEXCAP;
505         phy_write(phy, MII_1000BASETCONTROL, ctl2);
506
507         // XXX Should we set the sungem to GII now on 1000BT ?
508         
509         phy_write(phy, MII_BMCR, ctl);
510
511         return 0;
512 }
513
514 static int marvell_read_link(struct mii_phy *phy)
515 {
516         u16 status;
517
518         if (phy->autoneg) {
519                 status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
520                 if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
521                         return -EAGAIN;
522                 if (status & MII_M1011_PHY_SPEC_STATUS_1000)
523                         phy->speed = SPEED_1000;
524                 else if (status & MII_M1011_PHY_SPEC_STATUS_100)
525                         phy->speed = SPEED_100;
526                 else
527                         phy->speed = SPEED_10;
528                 if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
529                         phy->duplex = DUPLEX_FULL;
530                 else
531                         phy->duplex = DUPLEX_HALF;
532                 phy->pause = 0; /* XXX Check against spec ! */
533         }
534         /* On non-aneg, we assume what we put in BMCR is the speed,
535          * though magic-aneg shouldn't prevent this case from occurring
536          */
537
538         return 0;
539 }
540
541 static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
542 {
543         u16 ctl, adv;
544         
545         phy->autoneg = 1;
546         phy->speed = SPEED_10;
547         phy->duplex = DUPLEX_HALF;
548         phy->pause = 0;
549         phy->advertising = advertise;
550
551         /* Setup standard advertise */
552         adv = phy_read(phy, MII_ADVERTISE);
553         adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
554         if (advertise & ADVERTISED_10baseT_Half)
555                 adv |= ADVERTISE_10HALF;
556         if (advertise & ADVERTISED_10baseT_Full)
557                 adv |= ADVERTISE_10FULL;
558         if (advertise & ADVERTISED_100baseT_Half)
559                 adv |= ADVERTISE_100HALF;
560         if (advertise & ADVERTISED_100baseT_Full)
561                 adv |= ADVERTISE_100FULL;
562         phy_write(phy, MII_ADVERTISE, adv);
563
564         /* Start/Restart aneg */
565         ctl = phy_read(phy, MII_BMCR);
566         ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
567         phy_write(phy, MII_BMCR, ctl);
568
569         return 0;
570 }
571
572 static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
573 {
574         u16 ctl;
575         
576         phy->autoneg = 0;
577         phy->speed = speed;
578         phy->duplex = fd;
579         phy->pause = 0;
580
581         ctl = phy_read(phy, MII_BMCR);
582         ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
583
584         /* First reset the PHY */
585         phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
586
587         /* Select speed & duplex */
588         switch(speed) {
589         case SPEED_10:
590                 break;
591         case SPEED_100:
592                 ctl |= BMCR_SPEED100;
593                 break;
594         case SPEED_1000:
595         default:
596                 return -EINVAL;
597         }
598         if (fd == DUPLEX_FULL)
599                 ctl |= BMCR_FULLDPLX;
600         phy_write(phy, MII_BMCR, ctl);
601
602         return 0;
603 }
604
605 static int genmii_poll_link(struct mii_phy *phy)
606 {
607         u16 status;
608         
609         (void)phy_read(phy, MII_BMSR);
610         status = phy_read(phy, MII_BMSR);
611         if ((status & BMSR_LSTATUS) == 0)
612                 return 0;
613         if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
614                 return 0;
615         return 1;
616 }
617
618 static int genmii_read_link(struct mii_phy *phy)
619 {
620         u16 lpa;
621
622         if (phy->autoneg) {
623                 lpa = phy_read(phy, MII_LPA);
624
625                 if (lpa & (LPA_10FULL | LPA_100FULL))
626                         phy->duplex = DUPLEX_FULL;
627                 else
628                         phy->duplex = DUPLEX_HALF;
629                 if (lpa & (LPA_100FULL | LPA_100HALF))
630                         phy->speed = SPEED_100;
631                 else
632                         phy->speed = SPEED_10;
633                 phy->pause = 0;
634         }
635         /* On non-aneg, we assume what we put in BMCR is the speed,
636          * though magic-aneg shouldn't prevent this case from occurring
637          */
638
639          return 0;
640 }
641
642
643 #define MII_BASIC_FEATURES      (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
644                                  SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
645                                  SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII)
646 #define MII_GBIT_FEATURES       (MII_BASIC_FEATURES | \
647                                  SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
648
649 /* Broadcom BCM 5201 */
650 static struct mii_phy_ops bcm5201_phy_ops = {
651         .init           = bcm5201_init,
652         .suspend        = bcm5201_suspend,
653         .setup_aneg     = genmii_setup_aneg,
654         .setup_forced   = genmii_setup_forced,
655         .poll_link      = genmii_poll_link,
656         .read_link      = genmii_read_link,
657 };
658
659 static struct mii_phy_def bcm5201_phy_def = {
660         .phy_id         = 0x00406210,
661         .phy_id_mask    = 0xfffffff0,
662         .name           = "BCM5201",
663         .features       = MII_BASIC_FEATURES,
664         .magic_aneg     = 1,
665         .ops            = &bcm5201_phy_ops
666 };
667
668 /* Broadcom BCM 5221 */
669 static struct mii_phy_ops bcm5221_phy_ops = {
670         .suspend        = bcm5221_suspend,
671         .init           = bcm5221_init,
672         .setup_aneg     = genmii_setup_aneg,
673         .setup_forced   = genmii_setup_forced,
674         .poll_link      = genmii_poll_link,
675         .read_link      = genmii_read_link,
676 };
677
678 static struct mii_phy_def bcm5221_phy_def = {
679         .phy_id         = 0x004061e0,
680         .phy_id_mask    = 0xfffffff0,
681         .name           = "BCM5221",
682         .features       = MII_BASIC_FEATURES,
683         .magic_aneg     = 1,
684         .ops            = &bcm5221_phy_ops
685 };
686
687 /* Broadcom BCM 5400 */
688 static struct mii_phy_ops bcm5400_phy_ops = {
689         .init           = bcm5400_init,
690         .suspend        = bcm5400_suspend,
691         .setup_aneg     = bcm54xx_setup_aneg,
692         .setup_forced   = bcm54xx_setup_forced,
693         .poll_link      = genmii_poll_link,
694         .read_link      = bcm54xx_read_link,
695 };
696
697 static struct mii_phy_def bcm5400_phy_def = {
698         .phy_id         = 0x00206040,
699         .phy_id_mask    = 0xfffffff0,
700         .name           = "BCM5400",
701         .features       = MII_GBIT_FEATURES,
702         .magic_aneg     = 1,
703         .ops            = &bcm5400_phy_ops
704 };
705
706 /* Broadcom BCM 5401 */
707 static struct mii_phy_ops bcm5401_phy_ops = {
708         .init           = bcm5401_init,
709         .suspend        = bcm5401_suspend,
710         .setup_aneg     = bcm54xx_setup_aneg,
711         .setup_forced   = bcm54xx_setup_forced,
712         .poll_link      = genmii_poll_link,
713         .read_link      = bcm54xx_read_link,
714 };
715
716 static struct mii_phy_def bcm5401_phy_def = {
717         .phy_id         = 0x00206050,
718         .phy_id_mask    = 0xfffffff0,
719         .name           = "BCM5401",
720         .features       = MII_GBIT_FEATURES,
721         .magic_aneg     = 1,
722         .ops            = &bcm5401_phy_ops
723 };
724
725 /* Broadcom BCM 5411 */
726 static struct mii_phy_ops bcm5411_phy_ops = {
727         .init           = bcm5411_init,
728         .suspend        = bcm5411_suspend,
729         .setup_aneg     = bcm54xx_setup_aneg,
730         .setup_forced   = bcm54xx_setup_forced,
731         .poll_link      = genmii_poll_link,
732         .read_link      = bcm54xx_read_link,
733 };
734
735 static struct mii_phy_def bcm5411_phy_def = {
736         .phy_id         = 0x00206070,
737         .phy_id_mask    = 0xfffffff0,
738         .name           = "BCM5411",
739         .features       = MII_GBIT_FEATURES,
740         .magic_aneg     = 1,
741         .ops            = &bcm5411_phy_ops
742 };
743
744 /* Broadcom BCM 5421 */
745 static struct mii_phy_ops bcm5421_phy_ops = {
746         .init           = bcm5421_init,
747         .suspend        = bcm5411_suspend,
748         .setup_aneg     = bcm54xx_setup_aneg,
749         .setup_forced   = bcm54xx_setup_forced,
750         .poll_link      = genmii_poll_link,
751         .read_link      = bcm54xx_read_link,
752 };
753
754 static struct mii_phy_def bcm5421_phy_def = {
755         .phy_id         = 0x002060e0,
756         .phy_id_mask    = 0xfffffff0,
757         .name           = "BCM5421",
758         .features       = MII_GBIT_FEATURES,
759         .magic_aneg     = 1,
760         .ops            = &bcm5421_phy_ops
761 };
762
763 /* Broadcom BCM 5421 built-in K2 */
764 static struct mii_phy_ops bcm5421k2_phy_ops = {
765         .init           = bcm5421k2_init,
766         .suspend        = bcm5411_suspend,
767         .setup_aneg     = bcm54xx_setup_aneg,
768         .setup_forced   = bcm54xx_setup_forced,
769         .poll_link      = genmii_poll_link,
770         .read_link      = bcm54xx_read_link,
771 };
772
773 static struct mii_phy_def bcm5421k2_phy_def = {
774         .phy_id         = 0x002062e0,
775         .phy_id_mask    = 0xfffffff0,
776         .name           = "BCM5421-K2",
777         .features       = MII_GBIT_FEATURES,
778         .magic_aneg     = 1,
779         .ops            = &bcm5421k2_phy_ops
780 };
781
782 /* Marvell 88E1101 (Apple seem to deal with 2 different revs,
783  * I masked out the 8 last bits to get both, but some specs
784  * would be useful here) --BenH.
785  */
786 static struct mii_phy_ops marvell_phy_ops = {
787         .setup_aneg     = marvell_setup_aneg,
788         .setup_forced   = marvell_setup_forced,
789         .poll_link      = genmii_poll_link,
790         .read_link      = marvell_read_link
791 };
792
793 static struct mii_phy_def marvell_phy_def = {
794         .phy_id         = 0x01410c00,
795         .phy_id_mask    = 0xffffff00,
796         .name           = "Marvell 88E1101",
797         .features       = MII_GBIT_FEATURES,
798         .magic_aneg     = 1,
799         .ops            = &marvell_phy_ops
800 };
801
802 /* Generic implementation for most 10/100 PHYs */
803 static struct mii_phy_ops generic_phy_ops = {
804         .setup_aneg     = genmii_setup_aneg,
805         .setup_forced   = genmii_setup_forced,
806         .poll_link      = genmii_poll_link,
807         .read_link      = genmii_read_link
808 };
809
810 static struct mii_phy_def genmii_phy_def = {
811         .phy_id         = 0x00000000,
812         .phy_id_mask    = 0x00000000,
813         .name           = "Generic MII",
814         .features       = MII_BASIC_FEATURES,
815         .magic_aneg     = 0,
816         .ops            = &generic_phy_ops
817 };
818
819 static struct mii_phy_def* mii_phy_table[] = {
820         &bcm5201_phy_def,
821         &bcm5221_phy_def,
822         &bcm5400_phy_def,
823         &bcm5401_phy_def,
824         &bcm5411_phy_def,
825         &bcm5421_phy_def,
826         &bcm5421k2_phy_def,
827         &marvell_phy_def,
828         &genmii_phy_def,
829         NULL
830 };
831
832 int mii_phy_probe(struct mii_phy *phy, int mii_id)
833 {
834         int rc;
835         u32 id;
836         struct mii_phy_def* def;
837         int i;
838
839         /* We do not reset the mii_phy structure as the driver
840          * may re-probe the PHY regulary
841          */
842         phy->mii_id = mii_id;
843         
844         /* Take PHY out of isloate mode and reset it. */
845         rc = reset_one_mii_phy(phy, mii_id);
846         if (rc)
847                 goto fail;
848
849         /* Read ID and find matching entry */   
850         id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
851         printk(KERN_DEBUG "PHY ID: %x, addr: %x\n", id, mii_id);
852         for (i=0; (def = mii_phy_table[i]) != NULL; i++)
853                 if ((id & def->phy_id_mask) == def->phy_id)
854                         break;
855         /* Should never be NULL (we have a generic entry), but... */
856         if (def == NULL)
857                 goto fail;
858
859         phy->def = def;
860         
861         return 0;
862 fail:
863         phy->speed = 0;
864         phy->duplex = 0;
865         phy->pause = 0;
866         phy->advertising = 0;
867         return -ENODEV;
868 }
869
870 EXPORT_SYMBOL(mii_phy_probe);
871 MODULE_LICENSE("GPL");
872