ia64/linux-2.6.18-xen.hg

view drivers/net/sungem_phy.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
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)
7 *
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
20 */
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 */
50 };
52 static inline int __phy_read(struct mii_phy* phy, int id, int reg)
53 {
54 return phy->mdio_read(phy->dev, id, reg);
55 }
57 static inline void __phy_write(struct mii_phy* phy, int id, int reg, int val)
58 {
59 phy->mdio_write(phy->dev, id, reg, val);
60 }
62 static inline int phy_read(struct mii_phy* phy, int reg)
63 {
64 return phy->mdio_read(phy->dev, phy->mii_id, reg);
65 }
67 static inline void phy_write(struct mii_phy* phy, int reg, int val)
68 {
69 phy->mdio_write(phy->dev, phy->mii_id, reg, val);
70 }
72 static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
73 {
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);
89 }
90 if ((val & BMCR_ISOLATE) && limit > 0)
91 __phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
93 return (limit <= 0);
94 }
96 static int bcm5201_init(struct mii_phy* phy)
97 {
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;
107 }
109 static int bcm5201_suspend(struct mii_phy* phy)
110 {
111 phy_write(phy, MII_BCM5201_INTERRUPT, 0);
112 phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
114 return 0;
115 }
117 static int bcm5221_init(struct mii_phy* phy)
118 {
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;
138 }
140 static int bcm5221_suspend(struct mii_phy* phy)
141 {
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;
153 }
155 static int bcm5400_init(struct mii_phy* phy)
156 {
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;
182 }
184 static int bcm5400_suspend(struct mii_phy* phy)
185 {
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;
190 }
192 static int bcm5401_init(struct mii_phy* phy)
193 {
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"
202 *
203 * WARNING ! OF and Darwin don't agree on the
204 * register addresses. OF seem to interpret the
205 * register numbers below as decimal
206 *
207 * Note: This should (and does) match tg3_init_5401phy_dsp
208 * in the tg3.c driver. -DaveM
209 */
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);
221 }
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;
238 }
240 static int bcm5401_suspend(struct mii_phy* phy)
241 {
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;
246 }
248 static int bcm5411_init(struct mii_phy* phy)
249 {
250 u16 data;
252 /* Here's some more Apple black magic to setup
253 * some voltage stuffs.
254 */
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
261 */
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;
275 }
277 static int generic_suspend(struct mii_phy* phy)
278 {
279 phy_write(phy, MII_BMCR, BMCR_PDOWN);
281 return 0;
282 }
284 static int bcm5421_init(struct mii_phy* phy)
285 {
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
294 */
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);
304 }
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);
310 }
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);
324 }
325 }
326 #endif /* CONFIG_PPC_PMAC */
328 return 0;
329 }
331 static int bcm5421_enable_fiber(struct mii_phy* phy)
332 {
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;
343 }
345 static int bcm5461_enable_fiber(struct mii_phy* phy)
346 {
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;
353 }
355 static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
356 {
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;
393 }
395 static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
396 {
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;
419 }
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;
428 }
430 static int bcm54xx_read_link(struct mii_phy *phy)
431 {
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);
445 }
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
448 */
450 return 0;
451 }
453 static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
454 {
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 ?
481 */
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;
498 }
500 static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
501 {
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
522 */
523 case SPEED_1000:
524 ctl |= BMCR_SPD2;
525 }
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 ;)
531 */
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;
548 }
550 static int marvell_read_link(struct mii_phy *phy)
551 {
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 ! */
569 }
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
572 */
574 return 0;
575 }
577 static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
578 {
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;
606 }
608 static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
609 {
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;
633 }
634 if (fd == DUPLEX_FULL)
635 ctl |= BMCR_FULLDPLX;
636 phy_write(phy, MII_BMCR, ctl);
638 return 0;
639 }
641 static int genmii_poll_link(struct mii_phy *phy)
642 {
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;
652 }
654 static int genmii_read_link(struct mii_phy *phy)
655 {
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;
670 }
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
673 */
675 return 0;
676 }
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,
693 };
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
702 };
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,
712 };
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
721 };
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,
731 };
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
740 };
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,
750 };
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
759 };
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,
769 };
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
778 };
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,
789 };
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
798 };
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,
808 };
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
817 };
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,
827 };
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
836 };
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,
846 };
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
855 };
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.
860 */
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
867 };
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
876 };
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
884 };
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
893 };
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
908 };
910 int mii_phy_probe(struct mii_phy *phy, int mii_id)
911 {
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
919 */
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;
946 }
948 EXPORT_SYMBOL(mii_phy_probe);
949 MODULE_LICENSE("GPL");