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