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
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
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
)
78 val
= __phy_read(phy
, phy_id
, MII_BMCR
);
79 val
&= ~(BMCR_ISOLATE
| BMCR_PDOWN
);
81 __phy_write(phy
, phy_id
, MII_BMCR
, val
);
86 val
= __phy_read(phy
, phy_id
, MII_BMCR
);
87 if ((val
& BMCR_RESET
) == 0)
91 if ((val
& BMCR_ISOLATE
) && limit
> 0)
92 __phy_write(phy
, phy_id
, MII_BMCR
, val
& ~BMCR_ISOLATE
);
97 static int bcm5201_init(struct mii_phy
* phy
)
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);
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
);
118 static int bcm5221_init(struct mii_phy
* phy
)
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
);
141 static int bcm5221_suspend(struct mii_phy
* phy
)
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
);
156 static int bcm5400_init(struct mii_phy
* phy
)
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
);
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
);
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
);
193 static int bcm5401_init(struct mii_phy
* phy
)
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
);
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
);
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
);
249 static int bcm5411_init(struct mii_phy
* phy
)
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
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
);
272 /* Reset and configure cascaded 10/100 PHY */
273 (void)reset_one_mii_phy(phy
, 0x1f);
278 static int generic_suspend(struct mii_phy
* phy
)
280 phy_write(phy
, MII_BMCR
, BMCR_PDOWN
);
285 static int bcm5421_init(struct mii_phy
* phy
)
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
))
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 */
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);
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);
356 static int bcm54xx_setup_aneg(struct mii_phy
*phy
, u32 advertise
)
361 phy
->speed
= SPEED_10
;
362 phy
->duplex
= DUPLEX_HALF
;
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
);
396 static int bcm54xx_setup_forced(struct mii_phy
*phy
, int speed
, int fd
)
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 */
416 ctl
|= BMCR_SPEED100
;
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
);
431 static int bcm54xx_read_link(struct mii_phy
*phy
)
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] ?
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
454 static int marvell_setup_aneg(struct mii_phy
*phy
, u32 advertise
)
459 phy
->speed
= SPEED_10
;
460 phy
->duplex
= DUPLEX_HALF
;
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
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
);
501 static int marvell_setup_forced(struct mii_phy
*phy
, int speed
, int fd
)
510 ctl
= phy_read(phy
, MII_BMCR
);
511 ctl
&= ~(BMCR_FULLDPLX
|BMCR_SPEED100
|BMCR_SPD2
|BMCR_ANENABLE
);
514 /* Select speed & duplex */
519 ctl
|= BMCR_SPEED100
;
521 /* I'm not sure about the one below, again, Darwin source is
522 * quite confusing and I lack chip specs
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
);
551 static int marvell_read_link(struct mii_phy
*phy
)
556 status
= phy_read(phy
, MII_M1011_PHY_SPEC_STATUS
);
557 if ((status
& MII_M1011_PHY_SPEC_STATUS_RESOLVED
) == 0)
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
;
564 phy
->speed
= SPEED_10
;
565 if (status
& MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX
)
566 phy
->duplex
= DUPLEX_FULL
;
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
578 static int genmii_setup_aneg(struct mii_phy
*phy
, u32 advertise
)
583 phy
->speed
= SPEED_10
;
584 phy
->duplex
= DUPLEX_HALF
;
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
);
609 static int genmii_setup_forced(struct mii_phy
*phy
, int speed
, int fd
)
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 */
629 ctl
|= BMCR_SPEED100
;
635 if (fd
== DUPLEX_FULL
)
636 ctl
|= BMCR_FULLDPLX
;
637 phy_write(phy
, MII_BMCR
, ctl
);
642 static int genmii_poll_link(struct mii_phy
*phy
)
646 (void)phy_read(phy
, MII_BMSR
);
647 status
= phy_read(phy
, MII_BMSR
);
648 if ((status
& BMSR_LSTATUS
) == 0)
650 if (phy
->autoneg
&& !(status
& BMSR_ANEGCOMPLETE
))
655 static int genmii_read_link(struct mii_phy
*phy
)
660 lpa
= phy_read(phy
, MII_LPA
);
662 if (lpa
& (LPA_10FULL
| LPA_100FULL
))
663 phy
->duplex
= DUPLEX_FULL
;
665 phy
->duplex
= DUPLEX_HALF
;
666 if (lpa
& (LPA_100FULL
| LPA_100HALF
))
667 phy
->speed
= SPEED_100
;
669 phy
->speed
= SPEED_10
;
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
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,
700 .features
= MII_BASIC_FEATURES
,
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,
719 .features
= MII_BASIC_FEATURES
,
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,
738 .features
= MII_GBIT_FEATURES
,
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,
757 .features
= MII_GBIT_FEATURES
,
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,
776 .features
= MII_GBIT_FEATURES
,
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,
796 .features
= MII_GBIT_FEATURES
,
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
,
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,
834 .features
= MII_GBIT_FEATURES
,
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
,
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
,
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
,
893 .ops
= &generic_phy_ops
896 static struct mii_phy_def
* mii_phy_table
[] = {
911 int mii_phy_probe(struct mii_phy
*phy
, int mii_id
)
915 struct mii_phy_def
* def
;
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
);
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
)
934 /* Should never be NULL (we have a generic entry), but... */
945 phy
->advertising
= 0;
949 EXPORT_SYMBOL(mii_phy_probe
);
950 MODULE_LICENSE("GPL");