Pull acpica into release branch
[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 #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 bcm5421_enable_fiber(struct mii_phy* phy)
333 {
334         /* enable fiber mode */
335         phy_write(phy, MII_NCONFIG, 0x9020);
336         /* LEDs active in both modes, autosense prio = fiber */
337         phy_write(phy, MII_NCONFIG, 0x945f);
338
339         /* switch off fibre autoneg */
340         phy_write(phy, MII_NCONFIG, 0xfc01);
341         phy_write(phy, 0x0b, 0x0004);
342
343         return 0;
344 }
345
346 static int bcm5461_enable_fiber(struct mii_phy* phy)
347 {
348         phy_write(phy, MII_NCONFIG, 0xfc0c);
349         phy_write(phy, MII_BMCR, 0x4140);
350         phy_write(phy, MII_NCONFIG, 0xfc0b);
351         phy_write(phy, MII_BMCR, 0x0140);
352
353         return 0;
354 }
355
356 static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
357 {
358         u16 ctl, adv;
359         
360         phy->autoneg = 1;
361         phy->speed = SPEED_10;
362         phy->duplex = DUPLEX_HALF;
363         phy->pause = 0;
364         phy->advertising = advertise;
365
366         /* Setup standard advertise */
367         adv = phy_read(phy, MII_ADVERTISE);
368         adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
369         if (advertise & ADVERTISED_10baseT_Half)
370                 adv |= ADVERTISE_10HALF;
371         if (advertise & ADVERTISED_10baseT_Full)
372                 adv |= ADVERTISE_10FULL;
373         if (advertise & ADVERTISED_100baseT_Half)
374                 adv |= ADVERTISE_100HALF;
375         if (advertise & ADVERTISED_100baseT_Full)
376                 adv |= ADVERTISE_100FULL;
377         phy_write(phy, MII_ADVERTISE, adv);
378
379         /* Setup 1000BT advertise */
380         adv = phy_read(phy, MII_1000BASETCONTROL);
381         adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP);
382         if (advertise & SUPPORTED_1000baseT_Half)
383                 adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
384         if (advertise & SUPPORTED_1000baseT_Full)
385                 adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
386         phy_write(phy, MII_1000BASETCONTROL, adv);
387
388         /* Start/Restart aneg */
389         ctl = phy_read(phy, MII_BMCR);
390         ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
391         phy_write(phy, MII_BMCR, ctl);
392
393         return 0;
394 }
395
396 static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
397 {
398         u16 ctl;
399         
400         phy->autoneg = 0;
401         phy->speed = speed;
402         phy->duplex = fd;
403         phy->pause = 0;
404
405         ctl = phy_read(phy, MII_BMCR);
406         ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
407
408         /* First reset the PHY */
409         phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
410
411         /* Select speed & duplex */
412         switch(speed) {
413         case SPEED_10:
414                 break;
415         case SPEED_100:
416                 ctl |= BMCR_SPEED100;
417                 break;
418         case SPEED_1000:
419                 ctl |= BMCR_SPD2;
420         }
421         if (fd == DUPLEX_FULL)
422                 ctl |= BMCR_FULLDPLX;
423
424         // XXX Should we set the sungem to GII now on 1000BT ?
425         
426         phy_write(phy, MII_BMCR, ctl);
427
428         return 0;
429 }
430
431 static int bcm54xx_read_link(struct mii_phy *phy)
432 {
433         int link_mode;  
434         u16 val;
435         
436         if (phy->autoneg) {
437                 val = phy_read(phy, MII_BCM5400_AUXSTATUS);
438                 link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
439                              MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
440                 phy->duplex = phy_BCM5400_link_table[link_mode][0] ? DUPLEX_FULL : DUPLEX_HALF;
441                 phy->speed = phy_BCM5400_link_table[link_mode][2] ?
442                                 SPEED_1000 :
443                                 (phy_BCM5400_link_table[link_mode][1] ? SPEED_100 : SPEED_10);
444                 val = phy_read(phy, MII_LPA);
445                 phy->pause = ((val & LPA_PAUSE) != 0);
446         }
447         /* On non-aneg, we assume what we put in BMCR is the speed,
448          * though magic-aneg shouldn't prevent this case from occurring
449          */
450
451         return 0;
452 }
453
454 static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
455 {
456         u16 ctl, adv;
457         
458         phy->autoneg = 1;
459         phy->speed = SPEED_10;
460         phy->duplex = DUPLEX_HALF;
461         phy->pause = 0;
462         phy->advertising = advertise;
463
464         /* Setup standard advertise */
465         adv = phy_read(phy, MII_ADVERTISE);
466         adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
467         if (advertise & ADVERTISED_10baseT_Half)
468                 adv |= ADVERTISE_10HALF;
469         if (advertise & ADVERTISED_10baseT_Full)
470                 adv |= ADVERTISE_10FULL;
471         if (advertise & ADVERTISED_100baseT_Half)
472                 adv |= ADVERTISE_100HALF;
473         if (advertise & ADVERTISED_100baseT_Full)
474                 adv |= ADVERTISE_100FULL;
475         phy_write(phy, MII_ADVERTISE, adv);
476
477         /* Setup 1000BT advertise & enable crossover detect
478          * XXX How do we advertise 1000BT ? Darwin source is
479          * confusing here, they read from specific control and
480          * write to control... Someone has specs for those
481          * beasts ?
482          */
483         adv = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
484         adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX;
485         adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
486                         MII_1000BASETCONTROL_HALFDUPLEXCAP);
487         if (advertise & SUPPORTED_1000baseT_Half)
488                 adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
489         if (advertise & SUPPORTED_1000baseT_Full)
490                 adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
491         phy_write(phy, MII_1000BASETCONTROL, adv);
492
493         /* Start/Restart aneg */
494         ctl = phy_read(phy, MII_BMCR);
495         ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
496         phy_write(phy, MII_BMCR, ctl);
497
498         return 0;
499 }
500
501 static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
502 {
503         u16 ctl, ctl2;
504         
505         phy->autoneg = 0;
506         phy->speed = speed;
507         phy->duplex = fd;
508         phy->pause = 0;
509
510         ctl = phy_read(phy, MII_BMCR);
511         ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
512         ctl |= BMCR_RESET;
513
514         /* Select speed & duplex */
515         switch(speed) {
516         case SPEED_10:
517                 break;
518         case SPEED_100:
519                 ctl |= BMCR_SPEED100;
520                 break;
521         /* I'm not sure about the one below, again, Darwin source is
522          * quite confusing and I lack chip specs
523          */
524         case SPEED_1000:
525                 ctl |= BMCR_SPD2;
526         }
527         if (fd == DUPLEX_FULL)
528                 ctl |= BMCR_FULLDPLX;
529
530         /* Disable crossover. Again, the way Apple does it is strange,
531          * though I don't assume they are wrong ;)
532          */
533         ctl2 = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
534         ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX |
535                 MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX |
536                 MII_1000BASETCONTROL_FULLDUPLEXCAP |
537                 MII_1000BASETCONTROL_HALFDUPLEXCAP);
538         if (speed == SPEED_1000)
539                 ctl2 |= (fd == DUPLEX_FULL) ?
540                         MII_1000BASETCONTROL_FULLDUPLEXCAP :
541                         MII_1000BASETCONTROL_HALFDUPLEXCAP;
542         phy_write(phy, MII_1000BASETCONTROL, ctl2);
543
544         // XXX Should we set the sungem to GII now on 1000BT ?
545         
546         phy_write(phy, MII_BMCR, ctl);
547
548         return 0;
549 }
550
551 static int marvell_read_link(struct mii_phy *phy)
552 {
553         u16 status;
554
555         if (phy->autoneg) {
556                 status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
557                 if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
558                         return -EAGAIN;
559                 if (status & MII_M1011_PHY_SPEC_STATUS_1000)
560                         phy->speed = SPEED_1000;
561                 else if (status & MII_M1011_PHY_SPEC_STATUS_100)
562                         phy->speed = SPEED_100;
563                 else
564                         phy->speed = SPEED_10;
565                 if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
566                         phy->duplex = DUPLEX_FULL;
567                 else
568                         phy->duplex = DUPLEX_HALF;
569                 phy->pause = 0; /* XXX Check against spec ! */
570         }
571         /* On non-aneg, we assume what we put in BMCR is the speed,
572          * though magic-aneg shouldn't prevent this case from occurring
573          */
574
575         return 0;
576 }
577
578 static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
579 {
580         u16 ctl, adv;
581         
582         phy->autoneg = 1;
583         phy->speed = SPEED_10;
584         phy->duplex = DUPLEX_HALF;
585         phy->pause = 0;
586         phy->advertising = advertise;
587
588         /* Setup standard advertise */
589         adv = phy_read(phy, MII_ADVERTISE);
590         adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
591         if (advertise & ADVERTISED_10baseT_Half)
592                 adv |= ADVERTISE_10HALF;
593         if (advertise & ADVERTISED_10baseT_Full)
594                 adv |= ADVERTISE_10FULL;
595         if (advertise & ADVERTISED_100baseT_Half)
596                 adv |= ADVERTISE_100HALF;
597         if (advertise & ADVERTISED_100baseT_Full)
598                 adv |= ADVERTISE_100FULL;
599         phy_write(phy, MII_ADVERTISE, adv);
600
601         /* Start/Restart aneg */
602         ctl = phy_read(phy, MII_BMCR);
603         ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
604         phy_write(phy, MII_BMCR, ctl);
605
606         return 0;
607 }
608
609 static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
610 {
611         u16 ctl;
612         
613         phy->autoneg = 0;
614         phy->speed = speed;
615         phy->duplex = fd;
616         phy->pause = 0;
617
618         ctl = phy_read(phy, MII_BMCR);
619         ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
620
621         /* First reset the PHY */
622         phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
623
624         /* Select speed & duplex */
625         switch(speed) {
626         case SPEED_10:
627                 break;
628         case SPEED_100:
629                 ctl |= BMCR_SPEED100;
630                 break;
631         case SPEED_1000:
632         default:
633                 return -EINVAL;
634         }
635         if (fd == DUPLEX_FULL)
636                 ctl |= BMCR_FULLDPLX;
637         phy_write(phy, MII_BMCR, ctl);
638
639         return 0;
640 }
641
642 static int genmii_poll_link(struct mii_phy *phy)
643 {
644         u16 status;
645         
646         (void)phy_read(phy, MII_BMSR);
647         status = phy_read(phy, MII_BMSR);
648         if ((status & BMSR_LSTATUS) == 0)
649                 return 0;
650         if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
651                 return 0;
652         return 1;
653 }
654
655 static int genmii_read_link(struct mii_phy *phy)
656 {
657         u16 lpa;
658
659         if (phy->autoneg) {
660                 lpa = phy_read(phy, MII_LPA);
661
662                 if (lpa & (LPA_10FULL | LPA_100FULL))
663                         phy->duplex = DUPLEX_FULL;
664                 else
665                         phy->duplex = DUPLEX_HALF;
666                 if (lpa & (LPA_100FULL | LPA_100HALF))
667                         phy->speed = SPEED_100;
668                 else
669                         phy->speed = SPEED_10;
670                 phy->pause = 0;
671         }
672         /* On non-aneg, we assume what we put in BMCR is the speed,
673          * though magic-aneg shouldn't prevent this case from occurring
674          */
675
676          return 0;
677 }
678
679
680 #define MII_BASIC_FEATURES      (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
681                                  SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
682                                  SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII)
683 #define MII_GBIT_FEATURES       (MII_BASIC_FEATURES | \
684                                  SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
685
686 /* Broadcom BCM 5201 */
687 static struct mii_phy_ops bcm5201_phy_ops = {
688         .init           = bcm5201_init,
689         .suspend        = bcm5201_suspend,
690         .setup_aneg     = genmii_setup_aneg,
691         .setup_forced   = genmii_setup_forced,
692         .poll_link      = genmii_poll_link,
693         .read_link      = genmii_read_link,
694 };
695
696 static struct mii_phy_def bcm5201_phy_def = {
697         .phy_id         = 0x00406210,
698         .phy_id_mask    = 0xfffffff0,
699         .name           = "BCM5201",
700         .features       = MII_BASIC_FEATURES,
701         .magic_aneg     = 1,
702         .ops            = &bcm5201_phy_ops
703 };
704
705 /* Broadcom BCM 5221 */
706 static struct mii_phy_ops bcm5221_phy_ops = {
707         .suspend        = bcm5221_suspend,
708         .init           = bcm5221_init,
709         .setup_aneg     = genmii_setup_aneg,
710         .setup_forced   = genmii_setup_forced,
711         .poll_link      = genmii_poll_link,
712         .read_link      = genmii_read_link,
713 };
714
715 static struct mii_phy_def bcm5221_phy_def = {
716         .phy_id         = 0x004061e0,
717         .phy_id_mask    = 0xfffffff0,
718         .name           = "BCM5221",
719         .features       = MII_BASIC_FEATURES,
720         .magic_aneg     = 1,
721         .ops            = &bcm5221_phy_ops
722 };
723
724 /* Broadcom BCM 5400 */
725 static struct mii_phy_ops bcm5400_phy_ops = {
726         .init           = bcm5400_init,
727         .suspend        = bcm5400_suspend,
728         .setup_aneg     = bcm54xx_setup_aneg,
729         .setup_forced   = bcm54xx_setup_forced,
730         .poll_link      = genmii_poll_link,
731         .read_link      = bcm54xx_read_link,
732 };
733
734 static struct mii_phy_def bcm5400_phy_def = {
735         .phy_id         = 0x00206040,
736         .phy_id_mask    = 0xfffffff0,
737         .name           = "BCM5400",
738         .features       = MII_GBIT_FEATURES,
739         .magic_aneg     = 1,
740         .ops            = &bcm5400_phy_ops
741 };
742
743 /* Broadcom BCM 5401 */
744 static struct mii_phy_ops bcm5401_phy_ops = {
745         .init           = bcm5401_init,
746         .suspend        = bcm5401_suspend,
747         .setup_aneg     = bcm54xx_setup_aneg,
748         .setup_forced   = bcm54xx_setup_forced,
749         .poll_link      = genmii_poll_link,
750         .read_link      = bcm54xx_read_link,
751 };
752
753 static struct mii_phy_def bcm5401_phy_def = {
754         .phy_id         = 0x00206050,
755         .phy_id_mask    = 0xfffffff0,
756         .name           = "BCM5401",
757         .features       = MII_GBIT_FEATURES,
758         .magic_aneg     = 1,
759         .ops            = &bcm5401_phy_ops
760 };
761
762 /* Broadcom BCM 5411 */
763 static struct mii_phy_ops bcm5411_phy_ops = {
764         .init           = bcm5411_init,
765         .suspend        = generic_suspend,
766         .setup_aneg     = bcm54xx_setup_aneg,
767         .setup_forced   = bcm54xx_setup_forced,
768         .poll_link      = genmii_poll_link,
769         .read_link      = bcm54xx_read_link,
770 };
771
772 static struct mii_phy_def bcm5411_phy_def = {
773         .phy_id         = 0x00206070,
774         .phy_id_mask    = 0xfffffff0,
775         .name           = "BCM5411",
776         .features       = MII_GBIT_FEATURES,
777         .magic_aneg     = 1,
778         .ops            = &bcm5411_phy_ops
779 };
780
781 /* Broadcom BCM 5421 */
782 static struct mii_phy_ops bcm5421_phy_ops = {
783         .init           = bcm5421_init,
784         .suspend        = generic_suspend,
785         .setup_aneg     = bcm54xx_setup_aneg,
786         .setup_forced   = bcm54xx_setup_forced,
787         .poll_link      = genmii_poll_link,
788         .read_link      = bcm54xx_read_link,
789         .enable_fiber   = bcm5421_enable_fiber,
790 };
791
792 static struct mii_phy_def bcm5421_phy_def = {
793         .phy_id         = 0x002060e0,
794         .phy_id_mask    = 0xfffffff0,
795         .name           = "BCM5421",
796         .features       = MII_GBIT_FEATURES,
797         .magic_aneg     = 1,
798         .ops            = &bcm5421_phy_ops
799 };
800
801 /* Broadcom BCM 5421 built-in K2 */
802 static struct mii_phy_ops bcm5421k2_phy_ops = {
803         .init           = bcm5421_init,
804         .suspend        = generic_suspend,
805         .setup_aneg     = bcm54xx_setup_aneg,
806         .setup_forced   = bcm54xx_setup_forced,
807         .poll_link      = genmii_poll_link,
808         .read_link      = bcm54xx_read_link,
809 };
810
811 static struct mii_phy_def bcm5421k2_phy_def = {
812         .phy_id         = 0x002062e0,
813         .phy_id_mask    = 0xfffffff0,
814         .name           = "BCM5421-K2",
815         .features       = MII_GBIT_FEATURES,
816         .magic_aneg     = 1,
817         .ops            = &bcm5421k2_phy_ops
818 };
819
820 static struct mii_phy_ops bcm5461_phy_ops = {
821         .init           = bcm5421_init,
822         .suspend        = generic_suspend,
823         .setup_aneg     = bcm54xx_setup_aneg,
824         .setup_forced   = bcm54xx_setup_forced,
825         .poll_link      = genmii_poll_link,
826         .read_link      = bcm54xx_read_link,
827         .enable_fiber   = bcm5461_enable_fiber,
828 };
829
830 static struct mii_phy_def bcm5461_phy_def = {
831         .phy_id         = 0x002060c0,
832         .phy_id_mask    = 0xfffffff0,
833         .name           = "BCM5461",
834         .features       = MII_GBIT_FEATURES,
835         .magic_aneg     = 1,
836         .ops            = &bcm5461_phy_ops
837 };
838
839 /* Broadcom BCM 5462 built-in Vesta */
840 static struct mii_phy_ops bcm5462V_phy_ops = {
841         .init           = bcm5421_init,
842         .suspend        = generic_suspend,
843         .setup_aneg     = bcm54xx_setup_aneg,
844         .setup_forced   = bcm54xx_setup_forced,
845         .poll_link      = genmii_poll_link,
846         .read_link      = bcm54xx_read_link,
847 };
848
849 static struct mii_phy_def bcm5462V_phy_def = {
850         .phy_id         = 0x002060d0,
851         .phy_id_mask    = 0xfffffff0,
852         .name           = "BCM5462-Vesta",
853         .features       = MII_GBIT_FEATURES,
854         .magic_aneg     = 1,
855         .ops            = &bcm5462V_phy_ops
856 };
857
858 /* Marvell 88E1101 (Apple seem to deal with 2 different revs,
859  * I masked out the 8 last bits to get both, but some specs
860  * would be useful here) --BenH.
861  */
862 static struct mii_phy_ops marvell_phy_ops = {
863         .suspend        = generic_suspend,
864         .setup_aneg     = marvell_setup_aneg,
865         .setup_forced   = marvell_setup_forced,
866         .poll_link      = genmii_poll_link,
867         .read_link      = marvell_read_link
868 };
869
870 static struct mii_phy_def marvell_phy_def = {
871         .phy_id         = 0x01410c00,
872         .phy_id_mask    = 0xffffff00,
873         .name           = "Marvell 88E1101",
874         .features       = MII_GBIT_FEATURES,
875         .magic_aneg     = 1,
876         .ops            = &marvell_phy_ops
877 };
878
879 /* Generic implementation for most 10/100 PHYs */
880 static struct mii_phy_ops generic_phy_ops = {
881         .setup_aneg     = genmii_setup_aneg,
882         .setup_forced   = genmii_setup_forced,
883         .poll_link      = genmii_poll_link,
884         .read_link      = genmii_read_link
885 };
886
887 static struct mii_phy_def genmii_phy_def = {
888         .phy_id         = 0x00000000,
889         .phy_id_mask    = 0x00000000,
890         .name           = "Generic MII",
891         .features       = MII_BASIC_FEATURES,
892         .magic_aneg     = 0,
893         .ops            = &generic_phy_ops
894 };
895
896 static struct mii_phy_def* mii_phy_table[] = {
897         &bcm5201_phy_def,
898         &bcm5221_phy_def,
899         &bcm5400_phy_def,
900         &bcm5401_phy_def,
901         &bcm5411_phy_def,
902         &bcm5421_phy_def,
903         &bcm5421k2_phy_def,
904         &bcm5461_phy_def,
905         &bcm5462V_phy_def,
906         &marvell_phy_def,
907         &genmii_phy_def,
908         NULL
909 };
910
911 int mii_phy_probe(struct mii_phy *phy, int mii_id)
912 {
913         int rc;
914         u32 id;
915         struct mii_phy_def* def;
916         int i;
917
918         /* We do not reset the mii_phy structure as the driver
919          * may re-probe the PHY regulary
920          */
921         phy->mii_id = mii_id;
922         
923         /* Take PHY out of isloate mode and reset it. */
924         rc = reset_one_mii_phy(phy, mii_id);
925         if (rc)
926                 goto fail;
927
928         /* Read ID and find matching entry */   
929         id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
930         printk(KERN_DEBUG "PHY ID: %x, addr: %x\n", id, mii_id);
931         for (i=0; (def = mii_phy_table[i]) != NULL; i++)
932                 if ((id & def->phy_id_mask) == def->phy_id)
933                         break;
934         /* Should never be NULL (we have a generic entry), but... */
935         if (def == NULL)
936                 goto fail;
937
938         phy->def = def;
939         
940         return 0;
941 fail:
942         phy->speed = 0;
943         phy->duplex = 0;
944         phy->pause = 0;
945         phy->advertising = 0;
946         return -ENODEV;
947 }
948
949 EXPORT_SYMBOL(mii_phy_probe);
950 MODULE_LICENSE("GPL");
951