xref: /openbmc/linux/drivers/net/sungem_phy.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
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  */
21 
22 #include <linux/config.h>
23 
24 #include <linux/module.h>
25 
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>
34 
35 #include "sungem_phy.h"
36 
37 /* Link modes of the BCM5400 PHY */
38 static int phy_BCM5400_link_table[8][3] = {
39 	{ 0, 0, 0 },	/* No link */
40 	{ 0, 0, 0 },	/* 10BT Half Duplex */
41 	{ 1, 0, 0 },	/* 10BT Full Duplex */
42 	{ 0, 1, 0 },	/* 100BT Half Duplex */
43 	{ 0, 1, 0 },	/* 100BT Half Duplex */
44 	{ 1, 1, 0 },	/* 100BT Full Duplex*/
45 	{ 1, 0, 1 },	/* 1000BT */
46 	{ 1, 0, 1 },	/* 1000BT */
47 };
48 
49 static inline int __phy_read(struct mii_phy* phy, int id, int reg)
50 {
51 	return phy->mdio_read(phy->dev, id, reg);
52 }
53 
54 static inline void __phy_write(struct mii_phy* phy, int id, int reg, int val)
55 {
56 	phy->mdio_write(phy->dev, id, reg, val);
57 }
58 
59 static inline int phy_read(struct mii_phy* phy, int reg)
60 {
61 	return phy->mdio_read(phy->dev, phy->mii_id, reg);
62 }
63 
64 static inline void phy_write(struct mii_phy* phy, int reg, int val)
65 {
66 	phy->mdio_write(phy->dev, phy->mii_id, reg, val);
67 }
68 
69 static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
70 {
71 	u16 val;
72 	int limit = 10000;
73 
74 	val = __phy_read(phy, phy_id, MII_BMCR);
75 	val &= ~(BMCR_ISOLATE | BMCR_PDOWN);
76 	val |= BMCR_RESET;
77 	__phy_write(phy, phy_id, MII_BMCR, val);
78 
79 	udelay(100);
80 
81 	while (limit--) {
82 		val = __phy_read(phy, phy_id, MII_BMCR);
83 		if ((val & BMCR_RESET) == 0)
84 			break;
85 		udelay(10);
86 	}
87 	if ((val & BMCR_ISOLATE) && limit > 0)
88 		__phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
89 
90 	return (limit <= 0);
91 }
92 
93 static int bcm5201_init(struct mii_phy* phy)
94 {
95 	u16 data;
96 
97 	data = phy_read(phy, MII_BCM5201_MULTIPHY);
98 	data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
99 	phy_write(phy, MII_BCM5201_MULTIPHY, data);
100 
101 	phy_write(phy, MII_BCM5201_INTERRUPT, 0);
102 
103 	return 0;
104 }
105 
106 static int bcm5201_suspend(struct mii_phy* phy)
107 {
108 	phy_write(phy, MII_BCM5201_INTERRUPT, 0);
109 	phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
110 
111 	return 0;
112 }
113 
114 static int bcm5221_init(struct mii_phy* phy)
115 {
116 	u16 data;
117 
118 	data = phy_read(phy, MII_BCM5221_TEST);
119 	phy_write(phy, MII_BCM5221_TEST,
120 		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
121 
122 	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
123 	phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
124 		data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
125 
126 	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
127 	phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
128 		data | MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR);
129 
130 	data = phy_read(phy, MII_BCM5221_TEST);
131 	phy_write(phy, MII_BCM5221_TEST,
132 		data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
133 
134 	return 0;
135 }
136 
137 static int bcm5221_suspend(struct mii_phy* phy)
138 {
139 	u16 data;
140 
141 	data = phy_read(phy, MII_BCM5221_TEST);
142 	phy_write(phy, MII_BCM5221_TEST,
143 		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
144 
145 	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
146 	phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
147 		  data | MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE);
148 
149 	return 0;
150 }
151 
152 static int bcm5400_init(struct mii_phy* phy)
153 {
154 	u16 data;
155 
156 	/* Configure for gigabit full duplex */
157 	data = phy_read(phy, MII_BCM5400_AUXCONTROL);
158 	data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
159 	phy_write(phy, MII_BCM5400_AUXCONTROL, data);
160 
161 	data = phy_read(phy, MII_BCM5400_GB_CONTROL);
162 	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
163 	phy_write(phy, MII_BCM5400_GB_CONTROL, data);
164 
165 	udelay(100);
166 
167 	/* Reset and configure cascaded 10/100 PHY */
168 	(void)reset_one_mii_phy(phy, 0x1f);
169 
170 	data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
171 	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
172 	__phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
173 
174 	data = phy_read(phy, MII_BCM5400_AUXCONTROL);
175 	data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
176 	phy_write(phy, MII_BCM5400_AUXCONTROL, data);
177 
178 	return 0;
179 }
180 
181 static int bcm5400_suspend(struct mii_phy* phy)
182 {
183 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
184 	phy_write(phy, MII_BMCR, BMCR_PDOWN);
185 #endif
186 	return 0;
187 }
188 
189 static int bcm5401_init(struct mii_phy* phy)
190 {
191 	u16 data;
192 	int rev;
193 
194 	rev = phy_read(phy, MII_PHYSID2) & 0x000f;
195 	if (rev == 0 || rev == 3) {
196 		/* Some revisions of 5401 appear to need this
197 		 * initialisation sequence to disable, according
198 		 * to OF, "tap power management"
199 		 *
200 		 * WARNING ! OF and Darwin don't agree on the
201 		 * register addresses. OF seem to interpret the
202 		 * register numbers below as decimal
203 		 *
204 		 * Note: This should (and does) match tg3_init_5401phy_dsp
205 		 *       in the tg3.c driver. -DaveM
206 		 */
207 		phy_write(phy, 0x18, 0x0c20);
208 		phy_write(phy, 0x17, 0x0012);
209 		phy_write(phy, 0x15, 0x1804);
210 		phy_write(phy, 0x17, 0x0013);
211 		phy_write(phy, 0x15, 0x1204);
212 		phy_write(phy, 0x17, 0x8006);
213 		phy_write(phy, 0x15, 0x0132);
214 		phy_write(phy, 0x17, 0x8006);
215 		phy_write(phy, 0x15, 0x0232);
216 		phy_write(phy, 0x17, 0x201f);
217 		phy_write(phy, 0x15, 0x0a20);
218 	}
219 
220 	/* Configure for gigabit full duplex */
221 	data = phy_read(phy, MII_BCM5400_GB_CONTROL);
222 	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
223 	phy_write(phy, MII_BCM5400_GB_CONTROL, data);
224 
225 	udelay(10);
226 
227 	/* Reset and configure cascaded 10/100 PHY */
228 	(void)reset_one_mii_phy(phy, 0x1f);
229 
230 	data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
231 	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
232 	__phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
233 
234 	return 0;
235 }
236 
237 static int bcm5401_suspend(struct mii_phy* phy)
238 {
239 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
240 	phy_write(phy, MII_BMCR, BMCR_PDOWN);
241 #endif
242 	return 0;
243 }
244 
245 static int bcm5411_init(struct mii_phy* phy)
246 {
247 	u16 data;
248 
249 	/* Here's some more Apple black magic to setup
250 	 * some voltage stuffs.
251 	 */
252 	phy_write(phy, 0x1c, 0x8c23);
253 	phy_write(phy, 0x1c, 0x8ca3);
254 	phy_write(phy, 0x1c, 0x8c23);
255 
256 	/* Here, Apple seems to want to reset it, do
257 	 * it as well
258 	 */
259 	phy_write(phy, MII_BMCR, BMCR_RESET);
260 	phy_write(phy, MII_BMCR, 0x1340);
261 
262 	data = phy_read(phy, MII_BCM5400_GB_CONTROL);
263 	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
264 	phy_write(phy, MII_BCM5400_GB_CONTROL, data);
265 
266 	udelay(10);
267 
268 	/* Reset and configure cascaded 10/100 PHY */
269 	(void)reset_one_mii_phy(phy, 0x1f);
270 
271 	return 0;
272 }
273 
274 static int bcm5411_suspend(struct mii_phy* phy)
275 {
276 	phy_write(phy, MII_BMCR, BMCR_PDOWN);
277 
278 	return 0;
279 }
280 
281 static int bcm5421_init(struct mii_phy* phy)
282 {
283 	u16 data;
284 	int rev;
285 
286 	rev = phy_read(phy, MII_PHYSID2) & 0x000f;
287 	if (rev == 0) {
288 		/* This is borrowed from MacOS
289 		 */
290 		phy_write(phy, 0x18, 0x1007);
291 		data = phy_read(phy, 0x18);
292 		phy_write(phy, 0x18, data | 0x0400);
293 		phy_write(phy, 0x18, 0x0007);
294 		data = phy_read(phy, 0x18);
295 		phy_write(phy, 0x18, data | 0x0800);
296 		phy_write(phy, 0x17, 0x000a);
297 		data = phy_read(phy, 0x15);
298 		phy_write(phy, 0x15, data | 0x0200);
299 	}
300 #if 0
301 	/* This has to be verified before I enable it */
302 	/* Enable automatic low-power */
303 	phy_write(phy, 0x1c, 0x9002);
304 	phy_write(phy, 0x1c, 0xa821);
305 	phy_write(phy, 0x1c, 0x941d);
306 #endif
307 	return 0;
308 }
309 
310 static int bcm5421k2_init(struct mii_phy* phy)
311 {
312 	/* Init code borrowed from OF */
313 	phy_write(phy, 4, 0x01e1);
314 	phy_write(phy, 9, 0x0300);
315 
316 	return 0;
317 }
318 
319 static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
320 {
321 	u16 ctl, adv;
322 
323 	phy->autoneg = 1;
324 	phy->speed = SPEED_10;
325 	phy->duplex = DUPLEX_HALF;
326 	phy->pause = 0;
327 	phy->advertising = advertise;
328 
329 	/* Setup standard advertise */
330 	adv = phy_read(phy, MII_ADVERTISE);
331 	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
332 	if (advertise & ADVERTISED_10baseT_Half)
333 		adv |= ADVERTISE_10HALF;
334 	if (advertise & ADVERTISED_10baseT_Full)
335 		adv |= ADVERTISE_10FULL;
336 	if (advertise & ADVERTISED_100baseT_Half)
337 		adv |= ADVERTISE_100HALF;
338 	if (advertise & ADVERTISED_100baseT_Full)
339 		adv |= ADVERTISE_100FULL;
340 	phy_write(phy, MII_ADVERTISE, adv);
341 
342 	/* Setup 1000BT advertise */
343 	adv = phy_read(phy, MII_1000BASETCONTROL);
344 	adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP);
345 	if (advertise & SUPPORTED_1000baseT_Half)
346 		adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
347 	if (advertise & SUPPORTED_1000baseT_Full)
348 		adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
349 	phy_write(phy, MII_1000BASETCONTROL, adv);
350 
351 	/* Start/Restart aneg */
352 	ctl = phy_read(phy, MII_BMCR);
353 	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
354 	phy_write(phy, MII_BMCR, ctl);
355 
356 	return 0;
357 }
358 
359 static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
360 {
361 	u16 ctl;
362 
363 	phy->autoneg = 0;
364 	phy->speed = speed;
365 	phy->duplex = fd;
366 	phy->pause = 0;
367 
368 	ctl = phy_read(phy, MII_BMCR);
369 	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
370 
371 	/* First reset the PHY */
372 	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
373 
374 	/* Select speed & duplex */
375 	switch(speed) {
376 	case SPEED_10:
377 		break;
378 	case SPEED_100:
379 		ctl |= BMCR_SPEED100;
380 		break;
381 	case SPEED_1000:
382 		ctl |= BMCR_SPD2;
383 	}
384 	if (fd == DUPLEX_FULL)
385 		ctl |= BMCR_FULLDPLX;
386 
387 	// XXX Should we set the sungem to GII now on 1000BT ?
388 
389 	phy_write(phy, MII_BMCR, ctl);
390 
391 	return 0;
392 }
393 
394 static int bcm54xx_read_link(struct mii_phy *phy)
395 {
396 	int link_mode;
397 	u16 val;
398 
399 	if (phy->autoneg) {
400 	    	val = phy_read(phy, MII_BCM5400_AUXSTATUS);
401 		link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
402 			     MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
403 		phy->duplex = phy_BCM5400_link_table[link_mode][0] ? DUPLEX_FULL : DUPLEX_HALF;
404 		phy->speed = phy_BCM5400_link_table[link_mode][2] ?
405 				SPEED_1000 :
406 				(phy_BCM5400_link_table[link_mode][1] ? SPEED_100 : SPEED_10);
407 		val = phy_read(phy, MII_LPA);
408 		phy->pause = ((val & LPA_PAUSE) != 0);
409 	}
410 	/* On non-aneg, we assume what we put in BMCR is the speed,
411 	 * though magic-aneg shouldn't prevent this case from occurring
412 	 */
413 
414 	return 0;
415 }
416 
417 static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
418 {
419 	u16 ctl, adv;
420 
421 	phy->autoneg = 1;
422 	phy->speed = SPEED_10;
423 	phy->duplex = DUPLEX_HALF;
424 	phy->pause = 0;
425 	phy->advertising = advertise;
426 
427 	/* Setup standard advertise */
428 	adv = phy_read(phy, MII_ADVERTISE);
429 	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
430 	if (advertise & ADVERTISED_10baseT_Half)
431 		adv |= ADVERTISE_10HALF;
432 	if (advertise & ADVERTISED_10baseT_Full)
433 		adv |= ADVERTISE_10FULL;
434 	if (advertise & ADVERTISED_100baseT_Half)
435 		adv |= ADVERTISE_100HALF;
436 	if (advertise & ADVERTISED_100baseT_Full)
437 		adv |= ADVERTISE_100FULL;
438 	phy_write(phy, MII_ADVERTISE, adv);
439 
440 	/* Setup 1000BT advertise & enable crossover detect
441 	 * XXX How do we advertise 1000BT ? Darwin source is
442 	 * confusing here, they read from specific control and
443 	 * write to control... Someone has specs for those
444 	 * beasts ?
445 	 */
446 	adv = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
447 	adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX;
448 	adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
449 			MII_1000BASETCONTROL_HALFDUPLEXCAP);
450 	if (advertise & SUPPORTED_1000baseT_Half)
451 		adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
452 	if (advertise & SUPPORTED_1000baseT_Full)
453 		adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
454 	phy_write(phy, MII_1000BASETCONTROL, adv);
455 
456 	/* Start/Restart aneg */
457 	ctl = phy_read(phy, MII_BMCR);
458 	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
459 	phy_write(phy, MII_BMCR, ctl);
460 
461 	return 0;
462 }
463 
464 static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
465 {
466 	u16 ctl, ctl2;
467 
468 	phy->autoneg = 0;
469 	phy->speed = speed;
470 	phy->duplex = fd;
471 	phy->pause = 0;
472 
473 	ctl = phy_read(phy, MII_BMCR);
474 	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
475 	ctl |= BMCR_RESET;
476 
477 	/* Select speed & duplex */
478 	switch(speed) {
479 	case SPEED_10:
480 		break;
481 	case SPEED_100:
482 		ctl |= BMCR_SPEED100;
483 		break;
484 	/* I'm not sure about the one below, again, Darwin source is
485 	 * quite confusing and I lack chip specs
486 	 */
487 	case SPEED_1000:
488 		ctl |= BMCR_SPD2;
489 	}
490 	if (fd == DUPLEX_FULL)
491 		ctl |= BMCR_FULLDPLX;
492 
493 	/* Disable crossover. Again, the way Apple does it is strange,
494 	 * though I don't assume they are wrong ;)
495 	 */
496 	ctl2 = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
497 	ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX |
498 		MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX |
499 		MII_1000BASETCONTROL_FULLDUPLEXCAP |
500 		MII_1000BASETCONTROL_HALFDUPLEXCAP);
501 	if (speed == SPEED_1000)
502 		ctl2 |= (fd == DUPLEX_FULL) ?
503 			MII_1000BASETCONTROL_FULLDUPLEXCAP :
504 			MII_1000BASETCONTROL_HALFDUPLEXCAP;
505 	phy_write(phy, MII_1000BASETCONTROL, ctl2);
506 
507 	// XXX Should we set the sungem to GII now on 1000BT ?
508 
509 	phy_write(phy, MII_BMCR, ctl);
510 
511 	return 0;
512 }
513 
514 static int marvell_read_link(struct mii_phy *phy)
515 {
516 	u16 status;
517 
518 	if (phy->autoneg) {
519 		status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
520 		if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
521 			return -EAGAIN;
522 		if (status & MII_M1011_PHY_SPEC_STATUS_1000)
523 			phy->speed = SPEED_1000;
524 		else if (status & MII_M1011_PHY_SPEC_STATUS_100)
525 			phy->speed = SPEED_100;
526 		else
527 			phy->speed = SPEED_10;
528 		if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
529 			phy->duplex = DUPLEX_FULL;
530 		else
531 			phy->duplex = DUPLEX_HALF;
532 		phy->pause = 0; /* XXX Check against spec ! */
533 	}
534 	/* On non-aneg, we assume what we put in BMCR is the speed,
535 	 * though magic-aneg shouldn't prevent this case from occurring
536 	 */
537 
538 	return 0;
539 }
540 
541 static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
542 {
543 	u16 ctl, adv;
544 
545 	phy->autoneg = 1;
546 	phy->speed = SPEED_10;
547 	phy->duplex = DUPLEX_HALF;
548 	phy->pause = 0;
549 	phy->advertising = advertise;
550 
551 	/* Setup standard advertise */
552 	adv = phy_read(phy, MII_ADVERTISE);
553 	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
554 	if (advertise & ADVERTISED_10baseT_Half)
555 		adv |= ADVERTISE_10HALF;
556 	if (advertise & ADVERTISED_10baseT_Full)
557 		adv |= ADVERTISE_10FULL;
558 	if (advertise & ADVERTISED_100baseT_Half)
559 		adv |= ADVERTISE_100HALF;
560 	if (advertise & ADVERTISED_100baseT_Full)
561 		adv |= ADVERTISE_100FULL;
562 	phy_write(phy, MII_ADVERTISE, adv);
563 
564 	/* Start/Restart aneg */
565 	ctl = phy_read(phy, MII_BMCR);
566 	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
567 	phy_write(phy, MII_BMCR, ctl);
568 
569 	return 0;
570 }
571 
572 static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
573 {
574 	u16 ctl;
575 
576 	phy->autoneg = 0;
577 	phy->speed = speed;
578 	phy->duplex = fd;
579 	phy->pause = 0;
580 
581 	ctl = phy_read(phy, MII_BMCR);
582 	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
583 
584 	/* First reset the PHY */
585 	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
586 
587 	/* Select speed & duplex */
588 	switch(speed) {
589 	case SPEED_10:
590 		break;
591 	case SPEED_100:
592 		ctl |= BMCR_SPEED100;
593 		break;
594 	case SPEED_1000:
595 	default:
596 		return -EINVAL;
597 	}
598 	if (fd == DUPLEX_FULL)
599 		ctl |= BMCR_FULLDPLX;
600 	phy_write(phy, MII_BMCR, ctl);
601 
602 	return 0;
603 }
604 
605 static int genmii_poll_link(struct mii_phy *phy)
606 {
607 	u16 status;
608 
609 	(void)phy_read(phy, MII_BMSR);
610 	status = phy_read(phy, MII_BMSR);
611 	if ((status & BMSR_LSTATUS) == 0)
612 		return 0;
613 	if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
614 		return 0;
615 	return 1;
616 }
617 
618 static int genmii_read_link(struct mii_phy *phy)
619 {
620 	u16 lpa;
621 
622 	if (phy->autoneg) {
623 		lpa = phy_read(phy, MII_LPA);
624 
625 		if (lpa & (LPA_10FULL | LPA_100FULL))
626 			phy->duplex = DUPLEX_FULL;
627 		else
628 			phy->duplex = DUPLEX_HALF;
629 		if (lpa & (LPA_100FULL | LPA_100HALF))
630 			phy->speed = SPEED_100;
631 		else
632 			phy->speed = SPEED_10;
633 		phy->pause = 0;
634 	}
635 	/* On non-aneg, we assume what we put in BMCR is the speed,
636 	 * though magic-aneg shouldn't prevent this case from occurring
637 	 */
638 
639 	 return 0;
640 }
641 
642 
643 #define MII_BASIC_FEATURES	(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
644 				 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
645 				 SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII)
646 #define MII_GBIT_FEATURES	(MII_BASIC_FEATURES | \
647 				 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
648 
649 /* Broadcom BCM 5201 */
650 static struct mii_phy_ops bcm5201_phy_ops = {
651 	.init		= bcm5201_init,
652 	.suspend	= bcm5201_suspend,
653 	.setup_aneg	= genmii_setup_aneg,
654 	.setup_forced	= genmii_setup_forced,
655 	.poll_link	= genmii_poll_link,
656 	.read_link	= genmii_read_link,
657 };
658 
659 static struct mii_phy_def bcm5201_phy_def = {
660 	.phy_id		= 0x00406210,
661 	.phy_id_mask	= 0xfffffff0,
662 	.name		= "BCM5201",
663 	.features	= MII_BASIC_FEATURES,
664 	.magic_aneg	= 1,
665 	.ops		= &bcm5201_phy_ops
666 };
667 
668 /* Broadcom BCM 5221 */
669 static struct mii_phy_ops bcm5221_phy_ops = {
670 	.suspend	= bcm5221_suspend,
671 	.init		= bcm5221_init,
672 	.setup_aneg	= genmii_setup_aneg,
673 	.setup_forced	= genmii_setup_forced,
674 	.poll_link	= genmii_poll_link,
675 	.read_link	= genmii_read_link,
676 };
677 
678 static struct mii_phy_def bcm5221_phy_def = {
679 	.phy_id		= 0x004061e0,
680 	.phy_id_mask	= 0xfffffff0,
681 	.name		= "BCM5221",
682 	.features	= MII_BASIC_FEATURES,
683 	.magic_aneg	= 1,
684 	.ops		= &bcm5221_phy_ops
685 };
686 
687 /* Broadcom BCM 5400 */
688 static struct mii_phy_ops bcm5400_phy_ops = {
689 	.init		= bcm5400_init,
690 	.suspend	= bcm5400_suspend,
691 	.setup_aneg	= bcm54xx_setup_aneg,
692 	.setup_forced	= bcm54xx_setup_forced,
693 	.poll_link	= genmii_poll_link,
694 	.read_link	= bcm54xx_read_link,
695 };
696 
697 static struct mii_phy_def bcm5400_phy_def = {
698 	.phy_id		= 0x00206040,
699 	.phy_id_mask	= 0xfffffff0,
700 	.name		= "BCM5400",
701 	.features	= MII_GBIT_FEATURES,
702 	.magic_aneg	= 1,
703 	.ops		= &bcm5400_phy_ops
704 };
705 
706 /* Broadcom BCM 5401 */
707 static struct mii_phy_ops bcm5401_phy_ops = {
708 	.init		= bcm5401_init,
709 	.suspend	= bcm5401_suspend,
710 	.setup_aneg	= bcm54xx_setup_aneg,
711 	.setup_forced	= bcm54xx_setup_forced,
712 	.poll_link	= genmii_poll_link,
713 	.read_link	= bcm54xx_read_link,
714 };
715 
716 static struct mii_phy_def bcm5401_phy_def = {
717 	.phy_id		= 0x00206050,
718 	.phy_id_mask	= 0xfffffff0,
719 	.name		= "BCM5401",
720 	.features	= MII_GBIT_FEATURES,
721 	.magic_aneg	= 1,
722 	.ops		= &bcm5401_phy_ops
723 };
724 
725 /* Broadcom BCM 5411 */
726 static struct mii_phy_ops bcm5411_phy_ops = {
727 	.init		= bcm5411_init,
728 	.suspend	= bcm5411_suspend,
729 	.setup_aneg	= bcm54xx_setup_aneg,
730 	.setup_forced	= bcm54xx_setup_forced,
731 	.poll_link	= genmii_poll_link,
732 	.read_link	= bcm54xx_read_link,
733 };
734 
735 static struct mii_phy_def bcm5411_phy_def = {
736 	.phy_id		= 0x00206070,
737 	.phy_id_mask	= 0xfffffff0,
738 	.name		= "BCM5411",
739 	.features	= MII_GBIT_FEATURES,
740 	.magic_aneg	= 1,
741 	.ops		= &bcm5411_phy_ops
742 };
743 
744 /* Broadcom BCM 5421 */
745 static struct mii_phy_ops bcm5421_phy_ops = {
746 	.init		= bcm5421_init,
747 	.suspend	= bcm5411_suspend,
748 	.setup_aneg	= bcm54xx_setup_aneg,
749 	.setup_forced	= bcm54xx_setup_forced,
750 	.poll_link	= genmii_poll_link,
751 	.read_link	= bcm54xx_read_link,
752 };
753 
754 static struct mii_phy_def bcm5421_phy_def = {
755 	.phy_id		= 0x002060e0,
756 	.phy_id_mask	= 0xfffffff0,
757 	.name		= "BCM5421",
758 	.features	= MII_GBIT_FEATURES,
759 	.magic_aneg	= 1,
760 	.ops		= &bcm5421_phy_ops
761 };
762 
763 /* Broadcom BCM 5421 built-in K2 */
764 static struct mii_phy_ops bcm5421k2_phy_ops = {
765 	.init		= bcm5421k2_init,
766 	.suspend	= bcm5411_suspend,
767 	.setup_aneg	= bcm54xx_setup_aneg,
768 	.setup_forced	= bcm54xx_setup_forced,
769 	.poll_link	= genmii_poll_link,
770 	.read_link	= bcm54xx_read_link,
771 };
772 
773 static struct mii_phy_def bcm5421k2_phy_def = {
774 	.phy_id		= 0x002062e0,
775 	.phy_id_mask	= 0xfffffff0,
776 	.name		= "BCM5421-K2",
777 	.features	= MII_GBIT_FEATURES,
778 	.magic_aneg	= 1,
779 	.ops		= &bcm5421k2_phy_ops
780 };
781 
782 /* Marvell 88E1101 (Apple seem to deal with 2 different revs,
783  * I masked out the 8 last bits to get both, but some specs
784  * would be useful here) --BenH.
785  */
786 static struct mii_phy_ops marvell_phy_ops = {
787 	.setup_aneg	= marvell_setup_aneg,
788 	.setup_forced	= marvell_setup_forced,
789 	.poll_link	= genmii_poll_link,
790 	.read_link	= marvell_read_link
791 };
792 
793 static struct mii_phy_def marvell_phy_def = {
794 	.phy_id		= 0x01410c00,
795 	.phy_id_mask	= 0xffffff00,
796 	.name		= "Marvell 88E1101",
797 	.features	= MII_GBIT_FEATURES,
798 	.magic_aneg	= 1,
799 	.ops		= &marvell_phy_ops
800 };
801 
802 /* Generic implementation for most 10/100 PHYs */
803 static struct mii_phy_ops generic_phy_ops = {
804 	.setup_aneg	= genmii_setup_aneg,
805 	.setup_forced	= genmii_setup_forced,
806 	.poll_link	= genmii_poll_link,
807 	.read_link	= genmii_read_link
808 };
809 
810 static struct mii_phy_def genmii_phy_def = {
811 	.phy_id		= 0x00000000,
812 	.phy_id_mask	= 0x00000000,
813 	.name		= "Generic MII",
814 	.features	= MII_BASIC_FEATURES,
815 	.magic_aneg	= 0,
816 	.ops		= &generic_phy_ops
817 };
818 
819 static struct mii_phy_def* mii_phy_table[] = {
820 	&bcm5201_phy_def,
821 	&bcm5221_phy_def,
822 	&bcm5400_phy_def,
823 	&bcm5401_phy_def,
824 	&bcm5411_phy_def,
825 	&bcm5421_phy_def,
826 	&bcm5421k2_phy_def,
827 	&marvell_phy_def,
828 	&genmii_phy_def,
829 	NULL
830 };
831 
832 int mii_phy_probe(struct mii_phy *phy, int mii_id)
833 {
834 	int rc;
835 	u32 id;
836 	struct mii_phy_def* def;
837 	int i;
838 
839 	/* We do not reset the mii_phy structure as the driver
840 	 * may re-probe the PHY regulary
841 	 */
842 	phy->mii_id = mii_id;
843 
844 	/* Take PHY out of isloate mode and reset it. */
845 	rc = reset_one_mii_phy(phy, mii_id);
846 	if (rc)
847 		goto fail;
848 
849 	/* Read ID and find matching entry */
850 	id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
851 	printk(KERN_DEBUG "PHY ID: %x, addr: %x\n", id, mii_id);
852 	for (i=0; (def = mii_phy_table[i]) != NULL; i++)
853 		if ((id & def->phy_id_mask) == def->phy_id)
854 			break;
855 	/* Should never be NULL (we have a generic entry), but... */
856 	if (def == NULL)
857 		goto fail;
858 
859 	phy->def = def;
860 
861 	return 0;
862 fail:
863 	phy->speed = 0;
864 	phy->duplex = 0;
865 	phy->pause = 0;
866 	phy->advertising = 0;
867 	return -ENODEV;
868 }
869 
870 EXPORT_SYMBOL(mii_phy_probe);
871 MODULE_LICENSE("GPL");
872 
873