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