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