Linux 2.6.17.3
[linux/fpc-iii.git] / drivers / net / sungem_phy.c
blobb2ddd5e793035d3fa12742a7c4b8484662fff7e4
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)
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
22 #include <linux/config.h>
24 #include <linux/module.h>
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>
35 #ifdef CONFIG_PPC_PMAC
36 #include <asm/prom.h>
37 #endif
39 #include "sungem_phy.h"
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 */
53 static inline int __phy_read(struct mii_phy* phy, int id, int reg)
55 return phy->mdio_read(phy->dev, id, reg);
58 static inline void __phy_write(struct mii_phy* phy, int id, int reg, int val)
60 phy->mdio_write(phy->dev, id, reg, val);
63 static inline int phy_read(struct mii_phy* phy, int reg)
65 return phy->mdio_read(phy->dev, phy->mii_id, reg);
68 static inline void phy_write(struct mii_phy* phy, int reg, int val)
70 phy->mdio_write(phy->dev, phy->mii_id, reg, val);
73 static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
75 u16 val;
76 int limit = 10000;
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);
83 udelay(100);
85 while (limit--) {
86 val = __phy_read(phy, phy_id, MII_BMCR);
87 if ((val & BMCR_RESET) == 0)
88 break;
89 udelay(10);
91 if ((val & BMCR_ISOLATE) && limit > 0)
92 __phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
94 return (limit <= 0);
97 static int bcm5201_init(struct mii_phy* phy)
99 u16 data;
101 data = phy_read(phy, MII_BCM5201_MULTIPHY);
102 data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
103 phy_write(phy, MII_BCM5201_MULTIPHY, data);
105 phy_write(phy, MII_BCM5201_INTERRUPT, 0);
107 return 0;
110 static int bcm5201_suspend(struct mii_phy* phy)
112 phy_write(phy, MII_BCM5201_INTERRUPT, 0);
113 phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
115 return 0;
118 static int bcm5221_init(struct mii_phy* phy)
120 u16 data;
122 data = phy_read(phy, MII_BCM5221_TEST);
123 phy_write(phy, MII_BCM5221_TEST,
124 data | MII_BCM5221_TEST_ENABLE_SHADOWS);
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);
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);
134 data = phy_read(phy, MII_BCM5221_TEST);
135 phy_write(phy, MII_BCM5221_TEST,
136 data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
138 return 0;
141 static int bcm5221_suspend(struct mii_phy* phy)
143 u16 data;
145 data = phy_read(phy, MII_BCM5221_TEST);
146 phy_write(phy, MII_BCM5221_TEST,
147 data | MII_BCM5221_TEST_ENABLE_SHADOWS);
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);
153 return 0;
156 static int bcm5400_init(struct mii_phy* phy)
158 u16 data;
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);
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);
169 udelay(100);
171 /* Reset and configure cascaded 10/100 PHY */
172 (void)reset_one_mii_phy(phy, 0x1f);
174 data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
175 data |= MII_BCM5201_MULTIPHY_SERIALMODE;
176 __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
178 data = phy_read(phy, MII_BCM5400_AUXCONTROL);
179 data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
180 phy_write(phy, MII_BCM5400_AUXCONTROL, data);
182 return 0;
185 static int bcm5400_suspend(struct mii_phy* phy)
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;
193 static int bcm5401_init(struct mii_phy* phy)
195 u16 data;
196 int rev;
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"
204 * WARNING ! OF and Darwin don't agree on the
205 * register addresses. OF seem to interpret the
206 * register numbers below as decimal
208 * Note: This should (and does) match tg3_init_5401phy_dsp
209 * in the tg3.c driver. -DaveM
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);
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);
229 udelay(10);
231 /* Reset and configure cascaded 10/100 PHY */
232 (void)reset_one_mii_phy(phy, 0x1f);
234 data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
235 data |= MII_BCM5201_MULTIPHY_SERIALMODE;
236 __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
238 return 0;
241 static int bcm5401_suspend(struct mii_phy* phy)
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;
249 static int bcm5411_init(struct mii_phy* phy)
251 u16 data;
253 /* Here's some more Apple black magic to setup
254 * some voltage stuffs.
256 phy_write(phy, 0x1c, 0x8c23);
257 phy_write(phy, 0x1c, 0x8ca3);
258 phy_write(phy, 0x1c, 0x8c23);
260 /* Here, Apple seems to want to reset it, do
261 * it as well
263 phy_write(phy, MII_BMCR, BMCR_RESET);
264 phy_write(phy, MII_BMCR, 0x1340);
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);
270 udelay(10);
272 /* Reset and configure cascaded 10/100 PHY */
273 (void)reset_one_mii_phy(phy, 0x1f);
275 return 0;
278 static int generic_suspend(struct mii_phy* phy)
280 phy_write(phy, MII_BMCR, BMCR_PDOWN);
282 return 0;
285 static int bcm5421_init(struct mii_phy* phy)
287 u16 data;
288 unsigned int id;
290 id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
292 /* Revision 0 of 5421 needs some fixups */
293 if (id == 0x002060e0) {
294 /* This is borrowed from MacOS
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);
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);
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);
327 #endif /* CONFIG_PPC_PMAC */
329 return 0;
332 static int bcm5421_enable_fiber(struct mii_phy* phy)
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);
339 /* switch off fibre autoneg */
340 phy_write(phy, MII_NCONFIG, 0xfc01);
341 phy_write(phy, 0x0b, 0x0004);
343 return 0;
346 static int bcm5461_enable_fiber(struct mii_phy* phy)
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);
353 return 0;
356 static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
358 u16 ctl, adv;
360 phy->autoneg = 1;
361 phy->speed = SPEED_10;
362 phy->duplex = DUPLEX_HALF;
363 phy->pause = 0;
364 phy->advertising = advertise;
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);
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);
388 /* Start/Restart aneg */
389 ctl = phy_read(phy, MII_BMCR);
390 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
391 phy_write(phy, MII_BMCR, ctl);
393 return 0;
396 static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
398 u16 ctl;
400 phy->autoneg = 0;
401 phy->speed = speed;
402 phy->duplex = fd;
403 phy->pause = 0;
405 ctl = phy_read(phy, MII_BMCR);
406 ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
408 /* First reset the PHY */
409 phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
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;
421 if (fd == DUPLEX_FULL)
422 ctl |= BMCR_FULLDPLX;
424 // XXX Should we set the sungem to GII now on 1000BT ?
426 phy_write(phy, MII_BMCR, ctl);
428 return 0;
431 static int bcm54xx_read_link(struct mii_phy *phy)
433 int link_mode;
434 u16 val;
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);
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
451 return 0;
454 static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
456 u16 ctl, adv;
458 phy->autoneg = 1;
459 phy->speed = SPEED_10;
460 phy->duplex = DUPLEX_HALF;
461 phy->pause = 0;
462 phy->advertising = advertise;
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);
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 ?
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);
493 /* Start/Restart aneg */
494 ctl = phy_read(phy, MII_BMCR);
495 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
496 phy_write(phy, MII_BMCR, ctl);
498 return 0;
501 static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
503 u16 ctl, ctl2;
505 phy->autoneg = 0;
506 phy->speed = speed;
507 phy->duplex = fd;
508 phy->pause = 0;
510 ctl = phy_read(phy, MII_BMCR);
511 ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
512 ctl |= BMCR_RESET;
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
524 case SPEED_1000:
525 ctl |= BMCR_SPD2;
527 if (fd == DUPLEX_FULL)
528 ctl |= BMCR_FULLDPLX;
530 /* Disable crossover. Again, the way Apple does it is strange,
531 * though I don't assume they are wrong ;)
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);
544 // XXX Should we set the sungem to GII now on 1000BT ?
546 phy_write(phy, MII_BMCR, ctl);
548 return 0;
551 static int marvell_read_link(struct mii_phy *phy)
553 u16 status;
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 ! */
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
575 return 0;
578 static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
580 u16 ctl, adv;
582 phy->autoneg = 1;
583 phy->speed = SPEED_10;
584 phy->duplex = DUPLEX_HALF;
585 phy->pause = 0;
586 phy->advertising = advertise;
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);
601 /* Start/Restart aneg */
602 ctl = phy_read(phy, MII_BMCR);
603 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
604 phy_write(phy, MII_BMCR, ctl);
606 return 0;
609 static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
611 u16 ctl;
613 phy->autoneg = 0;
614 phy->speed = speed;
615 phy->duplex = fd;
616 phy->pause = 0;
618 ctl = phy_read(phy, MII_BMCR);
619 ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
621 /* First reset the PHY */
622 phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
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;
635 if (fd == DUPLEX_FULL)
636 ctl |= BMCR_FULLDPLX;
637 phy_write(phy, MII_BMCR, ctl);
639 return 0;
642 static int genmii_poll_link(struct mii_phy *phy)
644 u16 status;
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;
655 static int genmii_read_link(struct mii_phy *phy)
657 u16 lpa;
659 if (phy->autoneg) {
660 lpa = phy_read(phy, MII_LPA);
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;
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
676 return 0;
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)
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,
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
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,
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
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,
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
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,
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
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,
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
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,
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
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,
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
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,
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
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,
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
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.
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
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
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
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
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
911 int mii_phy_probe(struct mii_phy *phy, int mii_id)
913 int rc;
914 u32 id;
915 struct mii_phy_def* def;
916 int i;
918 /* We do not reset the mii_phy structure as the driver
919 * may re-probe the PHY regulary
921 phy->mii_id = mii_id;
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;
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;
938 phy->def = def;
940 return 0;
941 fail:
942 phy->speed = 0;
943 phy->duplex = 0;
944 phy->pause = 0;
945 phy->advertising = 0;
946 return -ENODEV;
949 EXPORT_SYMBOL(mii_phy_probe);
950 MODULE_LICENSE("GPL");