2 * PHY drivers for the sungem ethernet driver.
4 * This file could be shared with other drivers.
6 * (c) 2002, Benjamin Herrenscmidt (benh@kernel.crashing.org)
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
23 #include <linux/module.h>
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>
34 #ifdef CONFIG_PPC_PMAC
38 #include "sungem_phy.h"
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 */
52 static inline int __phy_read(struct mii_phy
* phy
, int id
, int reg
)
54 return phy
->mdio_read(phy
->dev
, id
, reg
);
57 static inline void __phy_write(struct mii_phy
* phy
, int id
, int reg
, int val
)
59 phy
->mdio_write(phy
->dev
, id
, reg
, val
);
62 static inline int phy_read(struct mii_phy
* phy
, int reg
)
64 return phy
->mdio_read(phy
->dev
, phy
->mii_id
, reg
);
67 static inline void phy_write(struct mii_phy
* phy
, int reg
, int val
)
69 phy
->mdio_write(phy
->dev
, phy
->mii_id
, reg
, val
);
72 static int reset_one_mii_phy(struct mii_phy
* phy
, int phy_id
)
77 val
= __phy_read(phy
, phy_id
, MII_BMCR
);
78 val
&= ~(BMCR_ISOLATE
| BMCR_PDOWN
);
80 __phy_write(phy
, phy_id
, MII_BMCR
, val
);
85 val
= __phy_read(phy
, phy_id
, MII_BMCR
);
86 if ((val
& BMCR_RESET
) == 0)
90 if ((val
& BMCR_ISOLATE
) && limit
> 0)
91 __phy_write(phy
, phy_id
, MII_BMCR
, val
& ~BMCR_ISOLATE
);
96 static int bcm5201_init(struct mii_phy
* phy
)
100 data
= phy_read(phy
, MII_BCM5201_MULTIPHY
);
101 data
&= ~MII_BCM5201_MULTIPHY_SUPERISOLATE
;
102 phy_write(phy
, MII_BCM5201_MULTIPHY
, data
);
104 phy_write(phy
, MII_BCM5201_INTERRUPT
, 0);
109 static int bcm5201_suspend(struct mii_phy
* phy
)
111 phy_write(phy
, MII_BCM5201_INTERRUPT
, 0);
112 phy_write(phy
, MII_BCM5201_MULTIPHY
, MII_BCM5201_MULTIPHY_SUPERISOLATE
);
117 static int bcm5221_init(struct mii_phy
* phy
)
121 data
= phy_read(phy
, MII_BCM5221_TEST
);
122 phy_write(phy
, MII_BCM5221_TEST
,
123 data
| MII_BCM5221_TEST_ENABLE_SHADOWS
);
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
);
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
);
133 data
= phy_read(phy
, MII_BCM5221_TEST
);
134 phy_write(phy
, MII_BCM5221_TEST
,
135 data
& ~MII_BCM5221_TEST_ENABLE_SHADOWS
);
140 static int bcm5221_suspend(struct mii_phy
* phy
)
144 data
= phy_read(phy
, MII_BCM5221_TEST
);
145 phy_write(phy
, MII_BCM5221_TEST
,
146 data
| MII_BCM5221_TEST_ENABLE_SHADOWS
);
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
);
155 static int bcm5400_init(struct mii_phy
* phy
)
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
);
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
);
170 /* Reset and configure cascaded 10/100 PHY */
171 (void)reset_one_mii_phy(phy
, 0x1f);
173 data
= __phy_read(phy
, 0x1f, MII_BCM5201_MULTIPHY
);
174 data
|= MII_BCM5201_MULTIPHY_SERIALMODE
;
175 __phy_write(phy
, 0x1f, MII_BCM5201_MULTIPHY
, data
);
177 data
= phy_read(phy
, MII_BCM5400_AUXCONTROL
);
178 data
&= ~MII_BCM5400_AUXCONTROL_PWR10BASET
;
179 phy_write(phy
, MII_BCM5400_AUXCONTROL
, data
);
184 static int bcm5400_suspend(struct mii_phy
* phy
)
186 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
187 phy_write(phy
, MII_BMCR
, BMCR_PDOWN
);
192 static int bcm5401_init(struct mii_phy
* phy
)
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"
203 * WARNING ! OF and Darwin don't agree on the
204 * register addresses. OF seem to interpret the
205 * register numbers below as decimal
207 * Note: This should (and does) match tg3_init_5401phy_dsp
208 * in the tg3.c driver. -DaveM
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);
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
);
230 /* Reset and configure cascaded 10/100 PHY */
231 (void)reset_one_mii_phy(phy
, 0x1f);
233 data
= __phy_read(phy
, 0x1f, MII_BCM5201_MULTIPHY
);
234 data
|= MII_BCM5201_MULTIPHY_SERIALMODE
;
235 __phy_write(phy
, 0x1f, MII_BCM5201_MULTIPHY
, data
);
240 static int bcm5401_suspend(struct mii_phy
* phy
)
242 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
243 phy_write(phy
, MII_BMCR
, BMCR_PDOWN
);
248 static int bcm5411_init(struct mii_phy
* phy
)
252 /* Here's some more Apple black magic to setup
253 * some voltage stuffs.
255 phy_write(phy
, 0x1c, 0x8c23);
256 phy_write(phy
, 0x1c, 0x8ca3);
257 phy_write(phy
, 0x1c, 0x8c23);
259 /* Here, Apple seems to want to reset it, do
262 phy_write(phy
, MII_BMCR
, BMCR_RESET
);
263 phy_write(phy
, MII_BMCR
, 0x1340);
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
);
271 /* Reset and configure cascaded 10/100 PHY */
272 (void)reset_one_mii_phy(phy
, 0x1f);
277 static int generic_suspend(struct mii_phy
* phy
)
279 phy_write(phy
, MII_BMCR
, BMCR_PDOWN
);
284 static int bcm5421_init(struct mii_phy
* phy
)
289 id
= (phy_read(phy
, MII_PHYSID1
) << 16 | phy_read(phy
, MII_PHYSID2
));
291 /* Revision 0 of 5421 needs some fixups */
292 if (id
== 0x002060e0) {
293 /* This is borrowed from MacOS
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);
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);
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
))
320 /* Enable automatic low-power */
321 phy_write(phy
, 0x1c, 0x9002);
322 phy_write(phy
, 0x1c, 0xa821);
323 phy_write(phy
, 0x1c, 0x941d);
326 #endif /* CONFIG_PPC_PMAC */
331 static int bcm5421_enable_fiber(struct mii_phy
* phy
)
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);
338 /* switch off fibre autoneg */
339 phy_write(phy
, MII_NCONFIG
, 0xfc01);
340 phy_write(phy
, 0x0b, 0x0004);
345 static int bcm5461_enable_fiber(struct mii_phy
* phy
)
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);
355 static int bcm54xx_setup_aneg(struct mii_phy
*phy
, u32 advertise
)
360 phy
->speed
= SPEED_10
;
361 phy
->duplex
= DUPLEX_HALF
;
363 phy
->advertising
= advertise
;
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
);
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
);
387 /* Start/Restart aneg */
388 ctl
= phy_read(phy
, MII_BMCR
);
389 ctl
|= (BMCR_ANENABLE
| BMCR_ANRESTART
);
390 phy_write(phy
, MII_BMCR
, ctl
);
395 static int bcm54xx_setup_forced(struct mii_phy
*phy
, int speed
, int fd
)
404 ctl
= phy_read(phy
, MII_BMCR
);
405 ctl
&= ~(BMCR_FULLDPLX
|BMCR_SPEED100
|BMCR_SPD2
|BMCR_ANENABLE
);
407 /* First reset the PHY */
408 phy_write(phy
, MII_BMCR
, ctl
| BMCR_RESET
);
410 /* Select speed & duplex */
415 ctl
|= BMCR_SPEED100
;
420 if (fd
== DUPLEX_FULL
)
421 ctl
|= BMCR_FULLDPLX
;
423 // XXX Should we set the sungem to GII now on 1000BT ?
425 phy_write(phy
, MII_BMCR
, ctl
);
430 static int bcm54xx_read_link(struct mii_phy
*phy
)
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] ?
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);
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
453 static int marvell_setup_aneg(struct mii_phy
*phy
, u32 advertise
)
458 phy
->speed
= SPEED_10
;
459 phy
->duplex
= DUPLEX_HALF
;
461 phy
->advertising
= advertise
;
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
);
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
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
);
492 /* Start/Restart aneg */
493 ctl
= phy_read(phy
, MII_BMCR
);
494 ctl
|= (BMCR_ANENABLE
| BMCR_ANRESTART
);
495 phy_write(phy
, MII_BMCR
, ctl
);
500 static int marvell_setup_forced(struct mii_phy
*phy
, int speed
, int fd
)
509 ctl
= phy_read(phy
, MII_BMCR
);
510 ctl
&= ~(BMCR_FULLDPLX
|BMCR_SPEED100
|BMCR_SPD2
|BMCR_ANENABLE
);
513 /* Select speed & duplex */
518 ctl
|= BMCR_SPEED100
;
520 /* I'm not sure about the one below, again, Darwin source is
521 * quite confusing and I lack chip specs
526 if (fd
== DUPLEX_FULL
)
527 ctl
|= BMCR_FULLDPLX
;
529 /* Disable crossover. Again, the way Apple does it is strange,
530 * though I don't assume they are wrong ;)
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
);
543 // XXX Should we set the sungem to GII now on 1000BT ?
545 phy_write(phy
, MII_BMCR
, ctl
);
550 static int marvell_read_link(struct mii_phy
*phy
)
555 status
= phy_read(phy
, MII_M1011_PHY_SPEC_STATUS
);
556 if ((status
& MII_M1011_PHY_SPEC_STATUS_RESOLVED
) == 0)
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
;
563 phy
->speed
= SPEED_10
;
564 if (status
& MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX
)
565 phy
->duplex
= DUPLEX_FULL
;
567 phy
->duplex
= DUPLEX_HALF
;
568 phy
->pause
= 0; /* XXX Check against spec ! */
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
577 static int genmii_setup_aneg(struct mii_phy
*phy
, u32 advertise
)
582 phy
->speed
= SPEED_10
;
583 phy
->duplex
= DUPLEX_HALF
;
585 phy
->advertising
= advertise
;
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
);
600 /* Start/Restart aneg */
601 ctl
= phy_read(phy
, MII_BMCR
);
602 ctl
|= (BMCR_ANENABLE
| BMCR_ANRESTART
);
603 phy_write(phy
, MII_BMCR
, ctl
);
608 static int genmii_setup_forced(struct mii_phy
*phy
, int speed
, int fd
)
617 ctl
= phy_read(phy
, MII_BMCR
);
618 ctl
&= ~(BMCR_FULLDPLX
|BMCR_SPEED100
|BMCR_ANENABLE
);
620 /* First reset the PHY */
621 phy_write(phy
, MII_BMCR
, ctl
| BMCR_RESET
);
623 /* Select speed & duplex */
628 ctl
|= BMCR_SPEED100
;
634 if (fd
== DUPLEX_FULL
)
635 ctl
|= BMCR_FULLDPLX
;
636 phy_write(phy
, MII_BMCR
, ctl
);
641 static int genmii_poll_link(struct mii_phy
*phy
)
645 (void)phy_read(phy
, MII_BMSR
);
646 status
= phy_read(phy
, MII_BMSR
);
647 if ((status
& BMSR_LSTATUS
) == 0)
649 if (phy
->autoneg
&& !(status
& BMSR_ANEGCOMPLETE
))
654 static int genmii_read_link(struct mii_phy
*phy
)
659 lpa
= phy_read(phy
, MII_LPA
);
661 if (lpa
& (LPA_10FULL
| LPA_100FULL
))
662 phy
->duplex
= DUPLEX_FULL
;
664 phy
->duplex
= DUPLEX_HALF
;
665 if (lpa
& (LPA_100FULL
| LPA_100HALF
))
666 phy
->speed
= SPEED_100
;
668 phy
->speed
= SPEED_10
;
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
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)
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
,
695 static struct mii_phy_def bcm5201_phy_def
= {
696 .phy_id
= 0x00406210,
697 .phy_id_mask
= 0xfffffff0,
699 .features
= MII_BASIC_FEATURES
,
701 .ops
= &bcm5201_phy_ops
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
,
714 static struct mii_phy_def bcm5221_phy_def
= {
715 .phy_id
= 0x004061e0,
716 .phy_id_mask
= 0xfffffff0,
718 .features
= MII_BASIC_FEATURES
,
720 .ops
= &bcm5221_phy_ops
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
,
733 static struct mii_phy_def bcm5400_phy_def
= {
734 .phy_id
= 0x00206040,
735 .phy_id_mask
= 0xfffffff0,
737 .features
= MII_GBIT_FEATURES
,
739 .ops
= &bcm5400_phy_ops
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
,
752 static struct mii_phy_def bcm5401_phy_def
= {
753 .phy_id
= 0x00206050,
754 .phy_id_mask
= 0xfffffff0,
756 .features
= MII_GBIT_FEATURES
,
758 .ops
= &bcm5401_phy_ops
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
,
771 static struct mii_phy_def bcm5411_phy_def
= {
772 .phy_id
= 0x00206070,
773 .phy_id_mask
= 0xfffffff0,
775 .features
= MII_GBIT_FEATURES
,
777 .ops
= &bcm5411_phy_ops
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
,
791 static struct mii_phy_def bcm5421_phy_def
= {
792 .phy_id
= 0x002060e0,
793 .phy_id_mask
= 0xfffffff0,
795 .features
= MII_GBIT_FEATURES
,
797 .ops
= &bcm5421_phy_ops
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
,
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
,
816 .ops
= &bcm5421k2_phy_ops
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
,
829 static struct mii_phy_def bcm5461_phy_def
= {
830 .phy_id
= 0x002060c0,
831 .phy_id_mask
= 0xfffffff0,
833 .features
= MII_GBIT_FEATURES
,
835 .ops
= &bcm5461_phy_ops
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
,
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
,
854 .ops
= &bcm5462V_phy_ops
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.
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
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
,
875 .ops
= &marvell_phy_ops
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
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
,
892 .ops
= &generic_phy_ops
895 static struct mii_phy_def
* mii_phy_table
[] = {
910 int mii_phy_probe(struct mii_phy
*phy
, int mii_id
)
914 struct mii_phy_def
* def
;
917 /* We do not reset the mii_phy structure as the driver
918 * may re-probe the PHY regulary
920 phy
->mii_id
= mii_id
;
922 /* Take PHY out of isloate mode and reset it. */
923 rc
= reset_one_mii_phy(phy
, mii_id
);
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
)
933 /* Should never be NULL (we have a generic entry), but... */
944 phy
->advertising
= 0;
948 EXPORT_SYMBOL(mii_phy_probe
);
949 MODULE_LICENSE("GPL");