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