[GFS2] inode-diet: Eliminate i_blksize from the inode structure
[linux-2.6/mini2440.git] / drivers / net / sungem_phy.c
blob49800b25907db7d9abd2f4672a456dac6399227c
1 /*
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)
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
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
35 #include <asm/prom.h>
36 #endif
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)
74 u16 val;
75 int limit = 10000;
77 val = __phy_read(phy, phy_id, MII_BMCR);
78 val &= ~(BMCR_ISOLATE | BMCR_PDOWN);
79 val |= BMCR_RESET;
80 __phy_write(phy, phy_id, MII_BMCR, val);
82 udelay(100);
84 while (limit--) {
85 val = __phy_read(phy, phy_id, MII_BMCR);
86 if ((val & BMCR_RESET) == 0)
87 break;
88 udelay(10);
90 if ((val & BMCR_ISOLATE) && limit > 0)
91 __phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
93 return (limit <= 0);
96 static int bcm5201_init(struct mii_phy* phy)
98 u16 data;
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);
106 return 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);
114 return 0;
117 static int bcm5221_init(struct mii_phy* phy)
119 u16 data;
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);
137 return 0;
140 static int bcm5221_suspend(struct mii_phy* phy)
142 u16 data;
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);
152 return 0;
155 static int bcm5400_init(struct mii_phy* phy)
157 u16 data;
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);
168 udelay(100);
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);
181 return 0;
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);
188 #endif
189 return 0;
192 static int bcm5401_init(struct mii_phy* phy)
194 u16 data;
195 int rev;
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);
228 udelay(10);
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);
237 return 0;
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);
244 #endif
245 return 0;
248 static int bcm5411_init(struct mii_phy* phy)
250 u16 data;
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
260 * it as well
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);
269 udelay(10);
271 /* Reset and configure cascaded 10/100 PHY */
272 (void)reset_one_mii_phy(phy, 0x1f);
274 return 0;
277 static int generic_suspend(struct mii_phy* phy)
279 phy_write(phy, MII_BMCR, BMCR_PDOWN);
281 return 0;
284 static int bcm5421_init(struct mii_phy* phy)
286 u16 data;
287 unsigned int id;
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))
318 can_low_power = 0;
319 if (can_low_power) {
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 */
328 return 0;
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);
342 return 0;
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);
352 return 0;
355 static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
357 u16 ctl, adv;
359 phy->autoneg = 1;
360 phy->speed = SPEED_10;
361 phy->duplex = DUPLEX_HALF;
362 phy->pause = 0;
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);
392 return 0;
395 static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
397 u16 ctl;
399 phy->autoneg = 0;
400 phy->speed = speed;
401 phy->duplex = fd;
402 phy->pause = 0;
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 */
411 switch(speed) {
412 case SPEED_10:
413 break;
414 case SPEED_100:
415 ctl |= BMCR_SPEED100;
416 break;
417 case SPEED_1000:
418 ctl |= BMCR_SPD2;
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);
427 return 0;
430 static int bcm54xx_read_link(struct mii_phy *phy)
432 int link_mode;
433 u16 val;
435 if (phy->autoneg) {
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] ?
441 SPEED_1000 :
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
450 return 0;
453 static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
455 u16 ctl, adv;
457 phy->autoneg = 1;
458 phy->speed = SPEED_10;
459 phy->duplex = DUPLEX_HALF;
460 phy->pause = 0;
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
480 * beasts ?
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);
497 return 0;
500 static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
502 u16 ctl, ctl2;
504 phy->autoneg = 0;
505 phy->speed = speed;
506 phy->duplex = fd;
507 phy->pause = 0;
509 ctl = phy_read(phy, MII_BMCR);
510 ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
511 ctl |= BMCR_RESET;
513 /* Select speed & duplex */
514 switch(speed) {
515 case SPEED_10:
516 break;
517 case SPEED_100:
518 ctl |= BMCR_SPEED100;
519 break;
520 /* I'm not sure about the one below, again, Darwin source is
521 * quite confusing and I lack chip specs
523 case SPEED_1000:
524 ctl |= BMCR_SPD2;
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);
547 return 0;
550 static int marvell_read_link(struct mii_phy *phy)
552 u16 status;
554 if (phy->autoneg) {
555 status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
556 if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
557 return -EAGAIN;
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;
562 else
563 phy->speed = SPEED_10;
564 if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
565 phy->duplex = DUPLEX_FULL;
566 else
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
574 return 0;
577 static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
579 u16 ctl, adv;
581 phy->autoneg = 1;
582 phy->speed = SPEED_10;
583 phy->duplex = DUPLEX_HALF;
584 phy->pause = 0;
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);
605 return 0;
608 static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
610 u16 ctl;
612 phy->autoneg = 0;
613 phy->speed = speed;
614 phy->duplex = fd;
615 phy->pause = 0;
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 */
624 switch(speed) {
625 case SPEED_10:
626 break;
627 case SPEED_100:
628 ctl |= BMCR_SPEED100;
629 break;
630 case SPEED_1000:
631 default:
632 return -EINVAL;
634 if (fd == DUPLEX_FULL)
635 ctl |= BMCR_FULLDPLX;
636 phy_write(phy, MII_BMCR, ctl);
638 return 0;
641 static int genmii_poll_link(struct mii_phy *phy)
643 u16 status;
645 (void)phy_read(phy, MII_BMSR);
646 status = phy_read(phy, MII_BMSR);
647 if ((status & BMSR_LSTATUS) == 0)
648 return 0;
649 if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
650 return 0;
651 return 1;
654 static int genmii_read_link(struct mii_phy *phy)
656 u16 lpa;
658 if (phy->autoneg) {
659 lpa = phy_read(phy, MII_LPA);
661 if (lpa & (LPA_10FULL | LPA_100FULL))
662 phy->duplex = DUPLEX_FULL;
663 else
664 phy->duplex = DUPLEX_HALF;
665 if (lpa & (LPA_100FULL | LPA_100HALF))
666 phy->speed = SPEED_100;
667 else
668 phy->speed = SPEED_10;
669 phy->pause = 0;
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
675 return 0;
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,
698 .name = "BCM5201",
699 .features = MII_BASIC_FEATURES,
700 .magic_aneg = 1,
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,
717 .name = "BCM5221",
718 .features = MII_BASIC_FEATURES,
719 .magic_aneg = 1,
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,
736 .name = "BCM5400",
737 .features = MII_GBIT_FEATURES,
738 .magic_aneg = 1,
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,
755 .name = "BCM5401",
756 .features = MII_GBIT_FEATURES,
757 .magic_aneg = 1,
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,
774 .name = "BCM5411",
775 .features = MII_GBIT_FEATURES,
776 .magic_aneg = 1,
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,
794 .name = "BCM5421",
795 .features = MII_GBIT_FEATURES,
796 .magic_aneg = 1,
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,
815 .magic_aneg = 1,
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,
832 .name = "BCM5461",
833 .features = MII_GBIT_FEATURES,
834 .magic_aneg = 1,
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,
853 .magic_aneg = 1,
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,
874 .magic_aneg = 1,
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,
891 .magic_aneg = 0,
892 .ops = &generic_phy_ops
895 static struct mii_phy_def* mii_phy_table[] = {
896 &bcm5201_phy_def,
897 &bcm5221_phy_def,
898 &bcm5400_phy_def,
899 &bcm5401_phy_def,
900 &bcm5411_phy_def,
901 &bcm5421_phy_def,
902 &bcm5421k2_phy_def,
903 &bcm5461_phy_def,
904 &bcm5462V_phy_def,
905 &marvell_phy_def,
906 &genmii_phy_def,
907 NULL
910 int mii_phy_probe(struct mii_phy *phy, int mii_id)
912 int rc;
913 u32 id;
914 struct mii_phy_def* def;
915 int i;
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);
924 if (rc)
925 goto fail;
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)
932 break;
933 /* Should never be NULL (we have a generic entry), but... */
934 if (def == NULL)
935 goto fail;
937 phy->def = def;
939 return 0;
940 fail:
941 phy->speed = 0;
942 phy->duplex = 0;
943 phy->pause = 0;
944 phy->advertising = 0;
945 return -ENODEV;
948 EXPORT_SYMBOL(mii_phy_probe);
949 MODULE_LICENSE("GPL");