xref: /linux/drivers/net/sungem_phy.c (revision 14b42963f64b98ab61fa9723c03d71aa5ef4f862)
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 
23 #include <linux/module.h>
24 
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>
33 
34 #ifdef CONFIG_PPC_PMAC
35 #include <asm/prom.h>
36 #endif
37 
38 #include "sungem_phy.h"
39 
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 };
51 
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 }
56 
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 }
61 
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 }
66 
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 }
71 
72 static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
73 {
74 	u16 val;
75 	int limit = 10000;
76 
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);
81 
82 	udelay(100);
83 
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);
92 
93 	return (limit <= 0);
94 }
95 
96 static int bcm5201_init(struct mii_phy* phy)
97 {
98 	u16 data;
99 
100 	data = phy_read(phy, MII_BCM5201_MULTIPHY);
101 	data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
102 	phy_write(phy, MII_BCM5201_MULTIPHY, data);
103 
104 	phy_write(phy, MII_BCM5201_INTERRUPT, 0);
105 
106 	return 0;
107 }
108 
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);
113 
114 	return 0;
115 }
116 
117 static int bcm5221_init(struct mii_phy* phy)
118 {
119 	u16 data;
120 
121 	data = phy_read(phy, MII_BCM5221_TEST);
122 	phy_write(phy, MII_BCM5221_TEST,
123 		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
124 
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);
128 
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);
132 
133 	data = phy_read(phy, MII_BCM5221_TEST);
134 	phy_write(phy, MII_BCM5221_TEST,
135 		data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
136 
137 	return 0;
138 }
139 
140 static int bcm5221_suspend(struct mii_phy* phy)
141 {
142 	u16 data;
143 
144 	data = phy_read(phy, MII_BCM5221_TEST);
145 	phy_write(phy, MII_BCM5221_TEST,
146 		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
147 
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);
151 
152 	return 0;
153 }
154 
155 static int bcm5400_init(struct mii_phy* phy)
156 {
157 	u16 data;
158 
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);
163 
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);
167 
168 	udelay(100);
169 
170 	/* Reset and configure cascaded 10/100 PHY */
171 	(void)reset_one_mii_phy(phy, 0x1f);
172 
173 	data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
174 	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
175 	__phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
176 
177 	data = phy_read(phy, MII_BCM5400_AUXCONTROL);
178 	data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
179 	phy_write(phy, MII_BCM5400_AUXCONTROL, data);
180 
181 	return 0;
182 }
183 
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 }
191 
192 static int bcm5401_init(struct mii_phy* phy)
193 {
194 	u16 data;
195 	int rev;
196 
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 	}
222 
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);
227 
228 	udelay(10);
229 
230 	/* Reset and configure cascaded 10/100 PHY */
231 	(void)reset_one_mii_phy(phy, 0x1f);
232 
233 	data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
234 	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
235 	__phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
236 
237 	return 0;
238 }
239 
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 }
247 
248 static int bcm5411_init(struct mii_phy* phy)
249 {
250 	u16 data;
251 
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);
258 
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);
264 
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);
268 
269 	udelay(10);
270 
271 	/* Reset and configure cascaded 10/100 PHY */
272 	(void)reset_one_mii_phy(phy, 0x1f);
273 
274 	return 0;
275 }
276 
277 static int generic_suspend(struct mii_phy* phy)
278 {
279 	phy_write(phy, MII_BMCR, BMCR_PDOWN);
280 
281 	return 0;
282 }
283 
284 static int bcm5421_init(struct mii_phy* phy)
285 {
286 	u16 data;
287 	unsigned int id;
288 
289 	id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
290 
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 	}
305 
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 	}
311 
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 */
327 
328 	return 0;
329 }
330 
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);
337 
338 	/* switch off fibre autoneg */
339 	phy_write(phy, MII_NCONFIG, 0xfc01);
340 	phy_write(phy, 0x0b, 0x0004);
341 
342 	return 0;
343 }
344 
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);
351 
352 	return 0;
353 }
354 
355 static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
356 {
357 	u16 ctl, adv;
358 
359 	phy->autoneg = 1;
360 	phy->speed = SPEED_10;
361 	phy->duplex = DUPLEX_HALF;
362 	phy->pause = 0;
363 	phy->advertising = advertise;
364 
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);
377 
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);
386 
387 	/* Start/Restart aneg */
388 	ctl = phy_read(phy, MII_BMCR);
389 	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
390 	phy_write(phy, MII_BMCR, ctl);
391 
392 	return 0;
393 }
394 
395 static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
396 {
397 	u16 ctl;
398 
399 	phy->autoneg = 0;
400 	phy->speed = speed;
401 	phy->duplex = fd;
402 	phy->pause = 0;
403 
404 	ctl = phy_read(phy, MII_BMCR);
405 	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
406 
407 	/* First reset the PHY */
408 	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
409 
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;
422 
423 	// XXX Should we set the sungem to GII now on 1000BT ?
424 
425 	phy_write(phy, MII_BMCR, ctl);
426 
427 	return 0;
428 }
429 
430 static int bcm54xx_read_link(struct mii_phy *phy)
431 {
432 	int link_mode;
433 	u16 val;
434 
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 	 */
449 
450 	return 0;
451 }
452 
453 static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
454 {
455 	u16 ctl, adv;
456 
457 	phy->autoneg = 1;
458 	phy->speed = SPEED_10;
459 	phy->duplex = DUPLEX_HALF;
460 	phy->pause = 0;
461 	phy->advertising = advertise;
462 
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);
475 
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);
491 
492 	/* Start/Restart aneg */
493 	ctl = phy_read(phy, MII_BMCR);
494 	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
495 	phy_write(phy, MII_BMCR, ctl);
496 
497 	return 0;
498 }
499 
500 static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
501 {
502 	u16 ctl, ctl2;
503 
504 	phy->autoneg = 0;
505 	phy->speed = speed;
506 	phy->duplex = fd;
507 	phy->pause = 0;
508 
509 	ctl = phy_read(phy, MII_BMCR);
510 	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
511 	ctl |= BMCR_RESET;
512 
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;
528 
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);
542 
543 	// XXX Should we set the sungem to GII now on 1000BT ?
544 
545 	phy_write(phy, MII_BMCR, ctl);
546 
547 	return 0;
548 }
549 
550 static int marvell_read_link(struct mii_phy *phy)
551 {
552 	u16 status;
553 
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 	 */
573 
574 	return 0;
575 }
576 
577 static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
578 {
579 	u16 ctl, adv;
580 
581 	phy->autoneg = 1;
582 	phy->speed = SPEED_10;
583 	phy->duplex = DUPLEX_HALF;
584 	phy->pause = 0;
585 	phy->advertising = advertise;
586 
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);
599 
600 	/* Start/Restart aneg */
601 	ctl = phy_read(phy, MII_BMCR);
602 	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
603 	phy_write(phy, MII_BMCR, ctl);
604 
605 	return 0;
606 }
607 
608 static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
609 {
610 	u16 ctl;
611 
612 	phy->autoneg = 0;
613 	phy->speed = speed;
614 	phy->duplex = fd;
615 	phy->pause = 0;
616 
617 	ctl = phy_read(phy, MII_BMCR);
618 	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
619 
620 	/* First reset the PHY */
621 	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
622 
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);
637 
638 	return 0;
639 }
640 
641 static int genmii_poll_link(struct mii_phy *phy)
642 {
643 	u16 status;
644 
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 }
653 
654 static int genmii_read_link(struct mii_phy *phy)
655 {
656 	u16 lpa;
657 
658 	if (phy->autoneg) {
659 		lpa = phy_read(phy, MII_LPA);
660 
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 	 */
674 
675 	 return 0;
676 }
677 
678 
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)
684 
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 };
694 
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 };
703 
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 };
713 
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 };
722 
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 };
732 
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 };
741 
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 };
751 
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 };
760 
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 };
770 
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 };
779 
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 };
790 
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 };
799 
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 };
809 
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 };
818 
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 };
828 
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 };
837 
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 };
847 
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 };
856 
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 };
868 
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 };
877 
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 };
885 
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 };
894 
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 };
909 
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;
916 
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;
921 
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;
926 
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;
936 
937 	phy->def = def;
938 
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 }
947 
948 EXPORT_SYMBOL(mii_phy_probe);
949 MODULE_LICENSE("GPL");
950 
951