More meth updates.
[linux-2.6/linux-mips.git] / drivers / net / sungem_phy.c
blob0240dfe882fa3f0a3c3debe9d309e94e13ede8ba
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 #include "sungem_phy.h"
37 /* Link modes of the BCM5400 PHY */
38 static int phy_BCM5400_link_table[8][3] = {
39 { 0, 0, 0 }, /* No link */
40 { 0, 0, 0 }, /* 10BT Half Duplex */
41 { 1, 0, 0 }, /* 10BT Full Duplex */
42 { 0, 1, 0 }, /* 100BT Half Duplex */
43 { 0, 1, 0 }, /* 100BT Half Duplex */
44 { 1, 1, 0 }, /* 100BT Full Duplex*/
45 { 1, 0, 1 }, /* 1000BT */
46 { 1, 0, 1 }, /* 1000BT */
49 static inline int __phy_read(struct mii_phy* phy, int id, int reg)
51 return phy->mdio_read(phy->dev, id, reg);
54 static inline void __phy_write(struct mii_phy* phy, int id, int reg, int val)
56 phy->mdio_write(phy->dev, id, reg, val);
59 static inline int phy_read(struct mii_phy* phy, int reg)
61 return phy->mdio_read(phy->dev, phy->mii_id, reg);
64 static inline void phy_write(struct mii_phy* phy, int reg, int val)
66 phy->mdio_write(phy->dev, phy->mii_id, reg, val);
69 static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
71 u16 val;
72 int limit = 10000;
74 val = __phy_read(phy, phy_id, MII_BMCR);
75 val &= ~BMCR_ISOLATE;
76 val |= BMCR_RESET;
77 __phy_write(phy, phy_id, MII_BMCR, val);
79 udelay(100);
81 while (limit--) {
82 val = __phy_read(phy, phy_id, MII_BMCR);
83 if ((val & BMCR_RESET) == 0)
84 break;
85 udelay(10);
87 if ((val & BMCR_ISOLATE) && limit > 0)
88 __phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
90 return (limit <= 0);
93 static int bcm5201_init(struct mii_phy* phy)
95 u16 data;
97 data = phy_read(phy, MII_BCM5201_MULTIPHY);
98 data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
99 phy_write(phy, MII_BCM5201_MULTIPHY, data);
101 return 0;
104 static int bcm5201_suspend(struct mii_phy* phy, int wol_options)
106 if (!wol_options)
107 phy_write(phy, MII_BCM5201_INTERRUPT, 0);
109 /* Here's a strange hack used by both MacOS 9 and X */
110 phy_write(phy, MII_LPA, phy_read(phy, MII_LPA));
112 if (!wol_options) {
113 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
114 u16 val = phy_read(phy, MII_BCM5201_AUXMODE2)
115 phy_write(phy, MII_BCM5201_AUXMODE2,
116 val & ~MII_BCM5201_AUXMODE2_LOWPOWER);
117 #endif
118 phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
121 return 0;
124 static int bcm5221_init(struct mii_phy* phy)
126 u16 data;
128 data = phy_read(phy, MII_BCM5221_TEST);
129 phy_write(phy, MII_BCM5221_TEST,
130 data | MII_BCM5221_TEST_ENABLE_SHADOWS);
132 data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
133 phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
134 data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
136 data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
137 phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
138 data | MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR);
140 data = phy_read(phy, MII_BCM5221_TEST);
141 phy_write(phy, MII_BCM5221_TEST,
142 data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
144 return 0;
147 static int bcm5400_init(struct mii_phy* phy)
149 u16 data;
151 /* Configure for gigabit full duplex */
152 data = phy_read(phy, MII_BCM5400_AUXCONTROL);
153 data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
154 phy_write(phy, MII_BCM5400_AUXCONTROL, data);
156 data = phy_read(phy, MII_BCM5400_GB_CONTROL);
157 data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
158 phy_write(phy, MII_BCM5400_GB_CONTROL, data);
160 mdelay(10);
162 /* Reset and configure cascaded 10/100 PHY */
163 (void)reset_one_mii_phy(phy, 0x1f);
165 data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
166 data |= MII_BCM5201_MULTIPHY_SERIALMODE;
167 __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
169 data = phy_read(phy, MII_BCM5400_AUXCONTROL);
170 data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
171 phy_write(phy, MII_BCM5400_AUXCONTROL, data);
173 return 0;
176 static int bcm5400_suspend(struct mii_phy* phy, int wol_options)
178 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
179 phy_write(phy, MII_BMCR, BMCR_PDOWN);
180 #endif
181 return 0;
184 static int bcm5401_init(struct mii_phy* phy)
186 u16 data;
187 int rev;
189 rev = phy_read(phy, MII_PHYSID2) & 0x000f;
190 if (rev == 0 || rev == 3) {
191 /* Some revisions of 5401 appear to need this
192 * initialisation sequence to disable, according
193 * to OF, "tap power management"
195 * WARNING ! OF and Darwin don't agree on the
196 * register addresses. OF seem to interpret the
197 * register numbers below as decimal
199 * Note: This should (and does) match tg3_init_5401phy_dsp
200 * in the tg3.c driver. -DaveM
202 phy_write(phy, 0x18, 0x0c20);
203 phy_write(phy, 0x17, 0x0012);
204 phy_write(phy, 0x15, 0x1804);
205 phy_write(phy, 0x17, 0x0013);
206 phy_write(phy, 0x15, 0x1204);
207 phy_write(phy, 0x17, 0x8006);
208 phy_write(phy, 0x15, 0x0132);
209 phy_write(phy, 0x17, 0x8006);
210 phy_write(phy, 0x15, 0x0232);
211 phy_write(phy, 0x17, 0x201f);
212 phy_write(phy, 0x15, 0x0a20);
215 /* Configure for gigabit full duplex */
216 data = phy_read(phy, MII_BCM5400_GB_CONTROL);
217 data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
218 phy_write(phy, MII_BCM5400_GB_CONTROL, data);
220 mdelay(10);
222 /* Reset and configure cascaded 10/100 PHY */
223 (void)reset_one_mii_phy(phy, 0x1f);
225 data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
226 data |= MII_BCM5201_MULTIPHY_SERIALMODE;
227 __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
229 return 0;
232 static int bcm5401_suspend(struct mii_phy* phy, int wol_options)
234 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
235 phy_write(phy, MII_BMCR, BMCR_PDOWN);
236 #endif
237 return 0;
240 static int bcm5411_init(struct mii_phy* phy)
242 u16 data;
244 /* Here's some more Apple black magic to setup
245 * some voltage stuffs.
247 phy_write(phy, 0x1c, 0x8c23);
248 phy_write(phy, 0x1c, 0x8ca3);
249 phy_write(phy, 0x1c, 0x8c23);
251 /* Here, Apple seems to want to reset it, do
252 * it as well
254 phy_write(phy, MII_BMCR, BMCR_RESET);
255 phy_write(phy, MII_BMCR, 0x1340);
257 data = phy_read(phy, MII_BCM5400_GB_CONTROL);
258 data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
259 phy_write(phy, MII_BCM5400_GB_CONTROL, data);
261 mdelay(10);
263 /* Reset and configure cascaded 10/100 PHY */
264 (void)reset_one_mii_phy(phy, 0x1f);
266 return 0;
269 static int bcm5411_suspend(struct mii_phy* phy, int wol_options)
271 phy_write(phy, MII_BMCR, BMCR_PDOWN);
273 return 0;
276 static int bcm5421_init(struct mii_phy* phy)
278 u16 data;
279 int rev;
281 rev = phy_read(phy, MII_PHYSID2) & 0x000f;
282 if (rev == 0) {
283 /* This is borrowed from MacOS
285 phy_write(phy, 0x18, 0x1007);
286 data = phy_read(phy, 0x18);
287 phy_write(phy, 0x18, data | 0x0400);
288 phy_write(phy, 0x18, 0x0007);
289 data = phy_read(phy, 0x18);
290 phy_write(phy, 0x18, data | 0x0800);
291 phy_write(phy, 0x17, 0x000a);
292 data = phy_read(phy, 0x15);
293 phy_write(phy, 0x15, data | 0x0200);
295 #if 0
296 /* This has to be verified before I enable it */
297 /* Enable automatic low-power */
298 phy_write(phy, 0x1c, 0x9002);
299 phy_write(phy, 0x1c, 0xa821);
300 phy_write(phy, 0x1c, 0x941d);
301 #endif
302 return 0;
305 static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
307 u16 ctl, adv;
309 phy->autoneg = 1;
310 phy->speed = SPEED_10;
311 phy->duplex = DUPLEX_HALF;
312 phy->pause = 0;
313 phy->advertising = advertise;
315 /* Setup standard advertise */
316 adv = phy_read(phy, MII_ADVERTISE);
317 adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
318 if (advertise & ADVERTISED_10baseT_Half)
319 adv |= ADVERTISE_10HALF;
320 if (advertise & ADVERTISED_10baseT_Full)
321 adv |= ADVERTISE_10FULL;
322 if (advertise & ADVERTISED_100baseT_Half)
323 adv |= ADVERTISE_100HALF;
324 if (advertise & ADVERTISED_100baseT_Full)
325 adv |= ADVERTISE_100FULL;
326 phy_write(phy, MII_ADVERTISE, adv);
328 /* Setup 1000BT advertise */
329 adv = phy_read(phy, MII_1000BASETCONTROL);
330 adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP);
331 if (advertise & SUPPORTED_1000baseT_Half)
332 adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
333 if (advertise & SUPPORTED_1000baseT_Full)
334 adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
335 phy_write(phy, MII_1000BASETCONTROL, adv);
337 /* Start/Restart aneg */
338 ctl = phy_read(phy, MII_BMCR);
339 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
340 phy_write(phy, MII_BMCR, ctl);
342 return 0;
345 static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
347 u16 ctl;
349 phy->autoneg = 0;
350 phy->speed = speed;
351 phy->duplex = fd;
352 phy->pause = 0;
354 ctl = phy_read(phy, MII_BMCR);
355 ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
357 /* First reset the PHY */
358 phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
360 /* Select speed & duplex */
361 switch(speed) {
362 case SPEED_10:
363 break;
364 case SPEED_100:
365 ctl |= BMCR_SPEED100;
366 break;
367 case SPEED_1000:
368 ctl |= BMCR_SPD2;
370 if (fd == DUPLEX_FULL)
371 ctl |= BMCR_FULLDPLX;
373 // XXX Should we set the sungem to GII now on 1000BT ?
375 phy_write(phy, MII_BMCR, ctl);
377 return 0;
380 static int bcm54xx_read_link(struct mii_phy *phy)
382 int link_mode;
383 u16 val;
385 if (phy->autoneg) {
386 val = phy_read(phy, MII_BCM5400_AUXSTATUS);
387 link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
388 MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
389 phy->duplex = phy_BCM5400_link_table[link_mode][0] ? DUPLEX_FULL : DUPLEX_HALF;
390 phy->speed = phy_BCM5400_link_table[link_mode][2] ?
391 SPEED_1000 :
392 (phy_BCM5400_link_table[link_mode][1] ? SPEED_100 : SPEED_10);
393 val = phy_read(phy, MII_LPA);
394 phy->pause = ((val & LPA_PAUSE) != 0);
396 /* On non-aneg, we assume what we put in BMCR is the speed,
397 * though magic-aneg shouldn't prevent this case from occurring
400 return 0;
403 static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
405 u16 ctl, adv;
407 phy->autoneg = 1;
408 phy->speed = SPEED_10;
409 phy->duplex = DUPLEX_HALF;
410 phy->pause = 0;
411 phy->advertising = advertise;
413 /* Setup standard advertise */
414 adv = phy_read(phy, MII_ADVERTISE);
415 adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
416 if (advertise & ADVERTISED_10baseT_Half)
417 adv |= ADVERTISE_10HALF;
418 if (advertise & ADVERTISED_10baseT_Full)
419 adv |= ADVERTISE_10FULL;
420 if (advertise & ADVERTISED_100baseT_Half)
421 adv |= ADVERTISE_100HALF;
422 if (advertise & ADVERTISED_100baseT_Full)
423 adv |= ADVERTISE_100FULL;
424 phy_write(phy, MII_ADVERTISE, adv);
426 /* Setup 1000BT advertise & enable crossover detect
427 * XXX How do we advertise 1000BT ? Darwin source is
428 * confusing here, they read from specific control and
429 * write to control... Someone has specs for those
430 * beasts ?
432 adv = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
433 adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX;
434 adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
435 MII_1000BASETCONTROL_HALFDUPLEXCAP);
436 if (advertise & SUPPORTED_1000baseT_Half)
437 adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
438 if (advertise & SUPPORTED_1000baseT_Full)
439 adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
440 phy_write(phy, MII_1000BASETCONTROL, adv);
442 /* Start/Restart aneg */
443 ctl = phy_read(phy, MII_BMCR);
444 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
445 phy_write(phy, MII_BMCR, ctl);
447 return 0;
450 static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
452 u16 ctl, ctl2;
454 phy->autoneg = 0;
455 phy->speed = speed;
456 phy->duplex = fd;
457 phy->pause = 0;
459 ctl = phy_read(phy, MII_BMCR);
460 ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
461 ctl |= BMCR_RESET;
463 /* Select speed & duplex */
464 switch(speed) {
465 case SPEED_10:
466 break;
467 case SPEED_100:
468 ctl |= BMCR_SPEED100;
469 break;
470 /* I'm not sure about the one below, again, Darwin source is
471 * quite confusing and I lack chip specs
473 case SPEED_1000:
474 ctl |= BMCR_SPD2;
476 if (fd == DUPLEX_FULL)
477 ctl |= BMCR_FULLDPLX;
479 /* Disable crossover. Again, the way Apple does it is strange,
480 * though I don't assume they are wrong ;)
482 ctl2 = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
483 ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX |
484 MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX |
485 MII_1000BASETCONTROL_FULLDUPLEXCAP |
486 MII_1000BASETCONTROL_HALFDUPLEXCAP);
487 if (speed == SPEED_1000)
488 ctl2 |= (fd == DUPLEX_FULL) ?
489 MII_1000BASETCONTROL_FULLDUPLEXCAP :
490 MII_1000BASETCONTROL_HALFDUPLEXCAP;
491 phy_write(phy, MII_1000BASETCONTROL, ctl2);
493 // XXX Should we set the sungem to GII now on 1000BT ?
495 phy_write(phy, MII_BMCR, ctl);
497 return 0;
500 static int marvell_read_link(struct mii_phy *phy)
502 u16 status;
504 if (phy->autoneg) {
505 status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
506 if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
507 return -EAGAIN;
508 if (status & MII_M1011_PHY_SPEC_STATUS_1000)
509 phy->speed = SPEED_1000;
510 else if (status & MII_M1011_PHY_SPEC_STATUS_100)
511 phy->speed = SPEED_100;
512 else
513 phy->speed = SPEED_10;
514 if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
515 phy->duplex = DUPLEX_FULL;
516 else
517 phy->duplex = DUPLEX_HALF;
518 phy->pause = 0; /* XXX Check against spec ! */
520 /* On non-aneg, we assume what we put in BMCR is the speed,
521 * though magic-aneg shouldn't prevent this case from occurring
524 return 0;
527 static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
529 u16 ctl, adv;
531 phy->autoneg = 1;
532 phy->speed = SPEED_10;
533 phy->duplex = DUPLEX_HALF;
534 phy->pause = 0;
535 phy->advertising = advertise;
537 /* Setup standard advertise */
538 adv = phy_read(phy, MII_ADVERTISE);
539 adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
540 if (advertise & ADVERTISED_10baseT_Half)
541 adv |= ADVERTISE_10HALF;
542 if (advertise & ADVERTISED_10baseT_Full)
543 adv |= ADVERTISE_10FULL;
544 if (advertise & ADVERTISED_100baseT_Half)
545 adv |= ADVERTISE_100HALF;
546 if (advertise & ADVERTISED_100baseT_Full)
547 adv |= ADVERTISE_100FULL;
548 phy_write(phy, MII_ADVERTISE, adv);
550 /* Start/Restart aneg */
551 ctl = phy_read(phy, MII_BMCR);
552 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
553 phy_write(phy, MII_BMCR, ctl);
555 return 0;
558 static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
560 u16 ctl;
562 phy->autoneg = 0;
563 phy->speed = speed;
564 phy->duplex = fd;
565 phy->pause = 0;
567 ctl = phy_read(phy, MII_BMCR);
568 ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
570 /* First reset the PHY */
571 phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
573 /* Select speed & duplex */
574 switch(speed) {
575 case SPEED_10:
576 break;
577 case SPEED_100:
578 ctl |= BMCR_SPEED100;
579 break;
580 case SPEED_1000:
581 default:
582 return -EINVAL;
584 if (fd == DUPLEX_FULL)
585 ctl |= BMCR_FULLDPLX;
586 phy_write(phy, MII_BMCR, ctl);
588 return 0;
591 static int genmii_poll_link(struct mii_phy *phy)
593 u16 status;
595 (void)phy_read(phy, MII_BMSR);
596 status = phy_read(phy, MII_BMSR);
597 if ((status & BMSR_LSTATUS) == 0)
598 return 0;
599 if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
600 return 0;
601 return 1;
604 static int genmii_read_link(struct mii_phy *phy)
606 u16 lpa;
608 if (phy->autoneg) {
609 lpa = phy_read(phy, MII_LPA);
611 if (lpa & (LPA_10FULL | LPA_100FULL))
612 phy->duplex = DUPLEX_FULL;
613 else
614 phy->duplex = DUPLEX_HALF;
615 if (lpa & (LPA_100FULL | LPA_100HALF))
616 phy->speed = SPEED_100;
617 else
618 phy->speed = SPEED_10;
619 phy->pause = 0;
621 /* On non-aneg, we assume what we put in BMCR is the speed,
622 * though magic-aneg shouldn't prevent this case from occurring
625 return 0;
629 #define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
630 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
631 SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII)
632 #define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \
633 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
635 /* Broadcom BCM 5201 */
636 static struct mii_phy_ops bcm5201_phy_ops = {
637 init: bcm5201_init,
638 suspend: bcm5201_suspend,
639 setup_aneg: genmii_setup_aneg,
640 setup_forced: genmii_setup_forced,
641 poll_link: genmii_poll_link,
642 read_link: genmii_read_link,
645 static struct mii_phy_def bcm5201_phy_def = {
646 phy_id: 0x00406210,
647 phy_id_mask: 0xfffffff0,
648 name: "BCM5201",
649 features: MII_BASIC_FEATURES,
650 magic_aneg: 0,
651 ops: &bcm5201_phy_ops
654 /* Broadcom BCM 5221 */
655 static struct mii_phy_ops bcm5221_phy_ops = {
656 suspend: bcm5201_suspend,
657 init: bcm5221_init,
658 setup_aneg: genmii_setup_aneg,
659 setup_forced: genmii_setup_forced,
660 poll_link: genmii_poll_link,
661 read_link: genmii_read_link,
664 static struct mii_phy_def bcm5221_phy_def = {
665 phy_id: 0x004061e0,
666 phy_id_mask: 0xfffffff0,
667 name: "BCM5221",
668 features: MII_BASIC_FEATURES,
669 magic_aneg: 0,
670 ops: &bcm5221_phy_ops
673 /* Broadcom BCM 5400 */
674 static struct mii_phy_ops bcm5400_phy_ops = {
675 init: bcm5400_init,
676 suspend: bcm5400_suspend,
677 setup_aneg: bcm54xx_setup_aneg,
678 setup_forced: bcm54xx_setup_forced,
679 poll_link: genmii_poll_link,
680 read_link: bcm54xx_read_link,
683 static struct mii_phy_def bcm5400_phy_def = {
684 phy_id: 0x00206040,
685 phy_id_mask: 0xfffffff0,
686 name: "BCM5400",
687 features: MII_GBIT_FEATURES,
688 magic_aneg: 1,
689 ops: &bcm5400_phy_ops
692 /* Broadcom BCM 5401 */
693 static struct mii_phy_ops bcm5401_phy_ops = {
694 init: bcm5401_init,
695 suspend: bcm5401_suspend,
696 setup_aneg: bcm54xx_setup_aneg,
697 setup_forced: bcm54xx_setup_forced,
698 poll_link: genmii_poll_link,
699 read_link: bcm54xx_read_link,
702 static struct mii_phy_def bcm5401_phy_def = {
703 phy_id: 0x00206050,
704 phy_id_mask: 0xfffffff0,
705 name: "BCM5401",
706 features: MII_GBIT_FEATURES,
707 magic_aneg: 1,
708 ops: &bcm5401_phy_ops
711 /* Broadcom BCM 5411 */
712 static struct mii_phy_ops bcm5411_phy_ops = {
713 init: bcm5411_init,
714 suspend: bcm5411_suspend,
715 setup_aneg: bcm54xx_setup_aneg,
716 setup_forced: bcm54xx_setup_forced,
717 poll_link: genmii_poll_link,
718 read_link: bcm54xx_read_link,
721 static struct mii_phy_def bcm5411_phy_def = {
722 phy_id: 0x00206070,
723 phy_id_mask: 0xfffffff0,
724 name: "BCM5411",
725 features: MII_GBIT_FEATURES,
726 magic_aneg: 1,
727 ops: &bcm5411_phy_ops
730 /* Broadcom BCM 5421 */
731 static struct mii_phy_ops bcm5421_phy_ops = {
732 init: bcm5421_init,
733 suspend: bcm5411_suspend,
734 setup_aneg: bcm54xx_setup_aneg,
735 setup_forced: bcm54xx_setup_forced,
736 poll_link: genmii_poll_link,
737 read_link: bcm54xx_read_link,
740 static struct mii_phy_def bcm5421_phy_def = {
741 phy_id: 0x002060e0,
742 phy_id_mask: 0xfffffff0,
743 name: "BCM5421",
744 features: MII_GBIT_FEATURES,
745 magic_aneg: 1,
746 ops: &bcm5421_phy_ops
749 /* Marvell 88E1101 (Apple seem to deal with 2 different revs,
750 * I masked out the 8 last bits to get both, but some specs
751 * would be useful here) --BenH.
753 static struct mii_phy_ops marvell_phy_ops = {
754 setup_aneg: marvell_setup_aneg,
755 setup_forced: marvell_setup_forced,
756 poll_link: genmii_poll_link,
757 read_link: marvell_read_link
760 static struct mii_phy_def marvell_phy_def = {
761 phy_id: 0x01410c00,
762 phy_id_mask: 0xffffff00,
763 name: "Marvell 88E1101",
764 features: MII_GBIT_FEATURES,
765 magic_aneg: 1,
766 ops: &marvell_phy_ops
769 /* Generic implementation for most 10/100 PHYs */
770 static struct mii_phy_ops generic_phy_ops = {
771 setup_aneg: genmii_setup_aneg,
772 setup_forced: genmii_setup_forced,
773 poll_link: genmii_poll_link,
774 read_link: genmii_read_link
777 static struct mii_phy_def genmii_phy_def = {
778 phy_id: 0x00000000,
779 phy_id_mask: 0x00000000,
780 name: "Generic MII",
781 features: MII_BASIC_FEATURES,
782 magic_aneg: 0,
783 ops: &generic_phy_ops
786 static struct mii_phy_def* mii_phy_table[] = {
787 &bcm5201_phy_def,
788 &bcm5221_phy_def,
789 &bcm5400_phy_def,
790 &bcm5401_phy_def,
791 &bcm5411_phy_def,
792 &bcm5421_phy_def,
793 &marvell_phy_def,
794 &genmii_phy_def,
795 NULL
798 int mii_phy_probe(struct mii_phy *phy, int mii_id)
800 int rc;
801 u32 id;
802 struct mii_phy_def* def;
803 int i;
805 /* We do not reset the mii_phy structure as the driver
806 * may re-probe the PHY regulary
808 phy->mii_id = mii_id;
810 /* Take PHY out of isloate mode and reset it. */
811 rc = reset_one_mii_phy(phy, mii_id);
812 if (rc)
813 goto fail;
815 /* Read ID and find matching entry */
816 id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2))
817 & 0xfffffff0;
818 for (i=0; (def = mii_phy_table[i]) != NULL; i++)
819 if ((id & def->phy_id_mask) == def->phy_id)
820 break;
821 /* Should never be NULL (we have a generic entry), but... */
822 if (def == NULL)
823 goto fail;
825 phy->def = def;
827 return 0;
828 fail:
829 phy->speed = 0;
830 phy->duplex = 0;
831 phy->pause = 0;
832 phy->advertising = 0;
833 return -ENODEV;
836 EXPORT_SYMBOL(mii_phy_probe);
837 MODULE_LICENSE("GPL");