xref: /openbmc/linux/drivers/net/ethernet/ibm/emac/phy.c (revision b34e08d5)
1 /*
2  * drivers/net/ethernet/ibm/emac/phy.c
3  *
4  * Driver for PowerPC 4xx on-chip ethernet controller, PHY support.
5  * Borrowed from sungem_phy.c, though I only kept the generic MII
6  * driver for now.
7  *
8  * This file should be shared with other drivers or eventually
9  * merged as the "low level" part of miilib
10  *
11  * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
12  *                <benh@kernel.crashing.org>
13  *
14  * Based on the arch/ppc version of the driver:
15  *
16  * (c) 2003, Benjamin Herrenscmidt (benh@kernel.crashing.org)
17  * (c) 2004-2005, Eugene Surovegin <ebs@ebshome.net>
18  *
19  */
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/types.h>
23 #include <linux/netdevice.h>
24 #include <linux/mii.h>
25 #include <linux/ethtool.h>
26 #include <linux/delay.h>
27 
28 #include "emac.h"
29 #include "phy.h"
30 
31 #define phy_read _phy_read
32 #define phy_write _phy_write
33 
34 static inline int _phy_read(struct mii_phy *phy, int reg)
35 {
36 	return phy->mdio_read(phy->dev, phy->address, reg);
37 }
38 
39 static inline void _phy_write(struct mii_phy *phy, int reg, int val)
40 {
41 	phy->mdio_write(phy->dev, phy->address, reg, val);
42 }
43 
44 static inline int gpcs_phy_read(struct mii_phy *phy, int reg)
45 {
46 	return phy->mdio_read(phy->dev, phy->gpcs_address, reg);
47 }
48 
49 static inline void gpcs_phy_write(struct mii_phy *phy, int reg, int val)
50 {
51 	phy->mdio_write(phy->dev, phy->gpcs_address, reg, val);
52 }
53 
54 int emac_mii_reset_phy(struct mii_phy *phy)
55 {
56 	int val;
57 	int limit = 10000;
58 
59 	val = phy_read(phy, MII_BMCR);
60 	val &= ~(BMCR_ISOLATE | BMCR_ANENABLE);
61 	val |= BMCR_RESET;
62 	phy_write(phy, MII_BMCR, val);
63 
64 	udelay(300);
65 
66 	while (--limit) {
67 		val = phy_read(phy, MII_BMCR);
68 		if (val >= 0 && (val & BMCR_RESET) == 0)
69 			break;
70 		udelay(10);
71 	}
72 	if ((val & BMCR_ISOLATE) && limit > 0)
73 		phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
74 
75 	return limit <= 0;
76 }
77 
78 int emac_mii_reset_gpcs(struct mii_phy *phy)
79 {
80 	int val;
81 	int limit = 10000;
82 
83 	val = gpcs_phy_read(phy, MII_BMCR);
84 	val &= ~(BMCR_ISOLATE | BMCR_ANENABLE);
85 	val |= BMCR_RESET;
86 	gpcs_phy_write(phy, MII_BMCR, val);
87 
88 	udelay(300);
89 
90 	while (--limit) {
91 		val = gpcs_phy_read(phy, MII_BMCR);
92 		if (val >= 0 && (val & BMCR_RESET) == 0)
93 			break;
94 		udelay(10);
95 	}
96 	if ((val & BMCR_ISOLATE) && limit > 0)
97 		gpcs_phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
98 
99 	if (limit > 0 && phy->mode == PHY_MODE_SGMII) {
100 		/* Configure GPCS interface to recommended setting for SGMII */
101 		gpcs_phy_write(phy, 0x04, 0x8120); /* AsymPause, FDX */
102 		gpcs_phy_write(phy, 0x07, 0x2801); /* msg_pg, toggle */
103 		gpcs_phy_write(phy, 0x00, 0x0140); /* 1Gbps, FDX     */
104 	}
105 
106 	return limit <= 0;
107 }
108 
109 static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
110 {
111 	int ctl, adv;
112 
113 	phy->autoneg = AUTONEG_ENABLE;
114 	phy->speed = SPEED_10;
115 	phy->duplex = DUPLEX_HALF;
116 	phy->pause = phy->asym_pause = 0;
117 	phy->advertising = advertise;
118 
119 	ctl = phy_read(phy, MII_BMCR);
120 	if (ctl < 0)
121 		return ctl;
122 	ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
123 
124 	/* First clear the PHY */
125 	phy_write(phy, MII_BMCR, ctl);
126 
127 	/* Setup standard advertise */
128 	adv = phy_read(phy, MII_ADVERTISE);
129 	if (adv < 0)
130 		return adv;
131 	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
132 		 ADVERTISE_PAUSE_ASYM);
133 	if (advertise & ADVERTISED_10baseT_Half)
134 		adv |= ADVERTISE_10HALF;
135 	if (advertise & ADVERTISED_10baseT_Full)
136 		adv |= ADVERTISE_10FULL;
137 	if (advertise & ADVERTISED_100baseT_Half)
138 		adv |= ADVERTISE_100HALF;
139 	if (advertise & ADVERTISED_100baseT_Full)
140 		adv |= ADVERTISE_100FULL;
141 	if (advertise & ADVERTISED_Pause)
142 		adv |= ADVERTISE_PAUSE_CAP;
143 	if (advertise & ADVERTISED_Asym_Pause)
144 		adv |= ADVERTISE_PAUSE_ASYM;
145 	phy_write(phy, MII_ADVERTISE, adv);
146 
147 	if (phy->features &
148 	    (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) {
149 		adv = phy_read(phy, MII_CTRL1000);
150 		if (adv < 0)
151 			return adv;
152 		adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
153 		if (advertise & ADVERTISED_1000baseT_Full)
154 			adv |= ADVERTISE_1000FULL;
155 		if (advertise & ADVERTISED_1000baseT_Half)
156 			adv |= ADVERTISE_1000HALF;
157 		phy_write(phy, MII_CTRL1000, adv);
158 	}
159 
160 	/* Start/Restart aneg */
161 	ctl = phy_read(phy, MII_BMCR);
162 	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
163 	phy_write(phy, MII_BMCR, ctl);
164 
165 	return 0;
166 }
167 
168 static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
169 {
170 	int ctl;
171 
172 	phy->autoneg = AUTONEG_DISABLE;
173 	phy->speed = speed;
174 	phy->duplex = fd;
175 	phy->pause = phy->asym_pause = 0;
176 
177 	ctl = phy_read(phy, MII_BMCR);
178 	if (ctl < 0)
179 		return ctl;
180 	ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
181 
182 	/* First clear the PHY */
183 	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
184 
185 	/* Select speed & duplex */
186 	switch (speed) {
187 	case SPEED_10:
188 		break;
189 	case SPEED_100:
190 		ctl |= BMCR_SPEED100;
191 		break;
192 	case SPEED_1000:
193 		ctl |= BMCR_SPEED1000;
194 		break;
195 	default:
196 		return -EINVAL;
197 	}
198 	if (fd == DUPLEX_FULL)
199 		ctl |= BMCR_FULLDPLX;
200 	phy_write(phy, MII_BMCR, ctl);
201 
202 	return 0;
203 }
204 
205 static int genmii_poll_link(struct mii_phy *phy)
206 {
207 	int status;
208 
209 	/* Clear latched value with dummy read */
210 	phy_read(phy, MII_BMSR);
211 	status = phy_read(phy, MII_BMSR);
212 	if (status < 0 || (status & BMSR_LSTATUS) == 0)
213 		return 0;
214 	if (phy->autoneg == AUTONEG_ENABLE && !(status & BMSR_ANEGCOMPLETE))
215 		return 0;
216 	return 1;
217 }
218 
219 static int genmii_read_link(struct mii_phy *phy)
220 {
221 	if (phy->autoneg == AUTONEG_ENABLE) {
222 		int glpa = 0;
223 		int lpa = phy_read(phy, MII_LPA) & phy_read(phy, MII_ADVERTISE);
224 		if (lpa < 0)
225 			return lpa;
226 
227 		if (phy->features &
228 		    (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) {
229 			int adv = phy_read(phy, MII_CTRL1000);
230 			glpa = phy_read(phy, MII_STAT1000);
231 
232 			if (glpa < 0 || adv < 0)
233 				return adv;
234 
235 			glpa &= adv << 2;
236 		}
237 
238 		phy->speed = SPEED_10;
239 		phy->duplex = DUPLEX_HALF;
240 		phy->pause = phy->asym_pause = 0;
241 
242 		if (glpa & (LPA_1000FULL | LPA_1000HALF)) {
243 			phy->speed = SPEED_1000;
244 			if (glpa & LPA_1000FULL)
245 				phy->duplex = DUPLEX_FULL;
246 		} else if (lpa & (LPA_100FULL | LPA_100HALF)) {
247 			phy->speed = SPEED_100;
248 			if (lpa & LPA_100FULL)
249 				phy->duplex = DUPLEX_FULL;
250 		} else if (lpa & LPA_10FULL)
251 			phy->duplex = DUPLEX_FULL;
252 
253 		if (phy->duplex == DUPLEX_FULL) {
254 			phy->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
255 			phy->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
256 		}
257 	} else {
258 		int bmcr = phy_read(phy, MII_BMCR);
259 		if (bmcr < 0)
260 			return bmcr;
261 
262 		if (bmcr & BMCR_FULLDPLX)
263 			phy->duplex = DUPLEX_FULL;
264 		else
265 			phy->duplex = DUPLEX_HALF;
266 		if (bmcr & BMCR_SPEED1000)
267 			phy->speed = SPEED_1000;
268 		else if (bmcr & BMCR_SPEED100)
269 			phy->speed = SPEED_100;
270 		else
271 			phy->speed = SPEED_10;
272 
273 		phy->pause = phy->asym_pause = 0;
274 	}
275 	return 0;
276 }
277 
278 /* Generic implementation for most 10/100/1000 PHYs */
279 static struct mii_phy_ops generic_phy_ops = {
280 	.setup_aneg	= genmii_setup_aneg,
281 	.setup_forced	= genmii_setup_forced,
282 	.poll_link	= genmii_poll_link,
283 	.read_link	= genmii_read_link
284 };
285 
286 static struct mii_phy_def genmii_phy_def = {
287 	.phy_id		= 0x00000000,
288 	.phy_id_mask	= 0x00000000,
289 	.name		= "Generic MII",
290 	.ops		= &generic_phy_ops
291 };
292 
293 /* CIS8201 */
294 #define MII_CIS8201_10BTCSR	0x16
295 #define  TENBTCSR_ECHO_DISABLE	0x2000
296 #define MII_CIS8201_EPCR	0x17
297 #define  EPCR_MODE_MASK		0x3000
298 #define  EPCR_GMII_MODE		0x0000
299 #define  EPCR_RGMII_MODE	0x1000
300 #define  EPCR_TBI_MODE		0x2000
301 #define  EPCR_RTBI_MODE		0x3000
302 #define MII_CIS8201_ACSR	0x1c
303 #define  ACSR_PIN_PRIO_SELECT	0x0004
304 
305 static int cis8201_init(struct mii_phy *phy)
306 {
307 	int epcr;
308 
309 	epcr = phy_read(phy, MII_CIS8201_EPCR);
310 	if (epcr < 0)
311 		return epcr;
312 
313 	epcr &= ~EPCR_MODE_MASK;
314 
315 	switch (phy->mode) {
316 	case PHY_MODE_TBI:
317 		epcr |= EPCR_TBI_MODE;
318 		break;
319 	case PHY_MODE_RTBI:
320 		epcr |= EPCR_RTBI_MODE;
321 		break;
322 	case PHY_MODE_GMII:
323 		epcr |= EPCR_GMII_MODE;
324 		break;
325 	case PHY_MODE_RGMII:
326 	default:
327 		epcr |= EPCR_RGMII_MODE;
328 	}
329 
330 	phy_write(phy, MII_CIS8201_EPCR, epcr);
331 
332 	/* MII regs override strap pins */
333 	phy_write(phy, MII_CIS8201_ACSR,
334 		  phy_read(phy, MII_CIS8201_ACSR) | ACSR_PIN_PRIO_SELECT);
335 
336 	/* Disable TX_EN -> CRS echo mode, otherwise 10/HDX doesn't work */
337 	phy_write(phy, MII_CIS8201_10BTCSR,
338 		  phy_read(phy, MII_CIS8201_10BTCSR) | TENBTCSR_ECHO_DISABLE);
339 
340 	return 0;
341 }
342 
343 static struct mii_phy_ops cis8201_phy_ops = {
344 	.init		= cis8201_init,
345 	.setup_aneg	= genmii_setup_aneg,
346 	.setup_forced	= genmii_setup_forced,
347 	.poll_link	= genmii_poll_link,
348 	.read_link	= genmii_read_link
349 };
350 
351 static struct mii_phy_def cis8201_phy_def = {
352 	.phy_id		= 0x000fc410,
353 	.phy_id_mask	= 0x000ffff0,
354 	.name		= "CIS8201 Gigabit Ethernet",
355 	.ops		= &cis8201_phy_ops
356 };
357 
358 static struct mii_phy_def bcm5248_phy_def = {
359 
360 	.phy_id		= 0x0143bc00,
361 	.phy_id_mask	= 0x0ffffff0,
362 	.name		= "BCM5248 10/100 SMII Ethernet",
363 	.ops		= &generic_phy_ops
364 };
365 
366 static int m88e1111_init(struct mii_phy *phy)
367 {
368 	pr_debug("%s: Marvell 88E1111 Ethernet\n", __func__);
369 	phy_write(phy, 0x14, 0x0ce3);
370 	phy_write(phy, 0x18, 0x4101);
371 	phy_write(phy, 0x09, 0x0e00);
372 	phy_write(phy, 0x04, 0x01e1);
373 	phy_write(phy, 0x00, 0x9140);
374 	phy_write(phy, 0x00, 0x1140);
375 
376 	return  0;
377 }
378 
379 static int m88e1112_init(struct mii_phy *phy)
380 {
381 	/*
382 	 * Marvell 88E1112 PHY needs to have the SGMII MAC
383 	 * interace (page 2) properly configured to
384 	 * communicate with the 460EX/GT GPCS interface.
385 	 */
386 
387 	u16 reg_short;
388 
389 	pr_debug("%s: Marvell 88E1112 Ethernet\n", __func__);
390 
391 	/* Set access to Page 2 */
392 	phy_write(phy, 0x16, 0x0002);
393 
394 	phy_write(phy, 0x00, 0x0040); /* 1Gbps */
395 	reg_short = (u16)(phy_read(phy, 0x1a));
396 	reg_short |= 0x8000; /* bypass Auto-Negotiation */
397 	phy_write(phy, 0x1a, reg_short);
398 	emac_mii_reset_phy(phy); /* reset MAC interface */
399 
400 	/* Reset access to Page 0 */
401 	phy_write(phy, 0x16, 0x0000);
402 
403 	return  0;
404 }
405 
406 static int et1011c_init(struct mii_phy *phy)
407 {
408 	u16 reg_short;
409 
410 	reg_short = (u16)(phy_read(phy, 0x16));
411 	reg_short &= ~(0x7);
412 	reg_short |= 0x6;	/* RGMII Trace Delay*/
413 	phy_write(phy, 0x16, reg_short);
414 
415 	reg_short = (u16)(phy_read(phy, 0x17));
416 	reg_short &= ~(0x40);
417 	phy_write(phy, 0x17, reg_short);
418 
419 	phy_write(phy, 0x1c, 0x74f0);
420 	return 0;
421 }
422 
423 static struct mii_phy_ops et1011c_phy_ops = {
424 	.init		= et1011c_init,
425 	.setup_aneg	= genmii_setup_aneg,
426 	.setup_forced	= genmii_setup_forced,
427 	.poll_link	= genmii_poll_link,
428 	.read_link	= genmii_read_link
429 };
430 
431 static struct mii_phy_def et1011c_phy_def = {
432 	.phy_id		= 0x0282f000,
433 	.phy_id_mask	= 0x0fffff00,
434 	.name		= "ET1011C Gigabit Ethernet",
435 	.ops		= &et1011c_phy_ops
436 };
437 
438 
439 
440 
441 
442 static struct mii_phy_ops m88e1111_phy_ops = {
443 	.init		= m88e1111_init,
444 	.setup_aneg	= genmii_setup_aneg,
445 	.setup_forced	= genmii_setup_forced,
446 	.poll_link	= genmii_poll_link,
447 	.read_link	= genmii_read_link
448 };
449 
450 static struct mii_phy_def m88e1111_phy_def = {
451 
452 	.phy_id		= 0x01410CC0,
453 	.phy_id_mask	= 0x0ffffff0,
454 	.name		= "Marvell 88E1111 Ethernet",
455 	.ops		= &m88e1111_phy_ops,
456 };
457 
458 static struct mii_phy_ops m88e1112_phy_ops = {
459 	.init		= m88e1112_init,
460 	.setup_aneg	= genmii_setup_aneg,
461 	.setup_forced	= genmii_setup_forced,
462 	.poll_link	= genmii_poll_link,
463 	.read_link	= genmii_read_link
464 };
465 
466 static struct mii_phy_def m88e1112_phy_def = {
467 	.phy_id		= 0x01410C90,
468 	.phy_id_mask	= 0x0ffffff0,
469 	.name		= "Marvell 88E1112 Ethernet",
470 	.ops		= &m88e1112_phy_ops,
471 };
472 
473 static struct mii_phy_def *mii_phy_table[] = {
474 	&et1011c_phy_def,
475 	&cis8201_phy_def,
476 	&bcm5248_phy_def,
477 	&m88e1111_phy_def,
478 	&m88e1112_phy_def,
479 	&genmii_phy_def,
480 	NULL
481 };
482 
483 int emac_mii_phy_probe(struct mii_phy *phy, int address)
484 {
485 	struct mii_phy_def *def;
486 	int i;
487 	u32 id;
488 
489 	phy->autoneg = AUTONEG_DISABLE;
490 	phy->advertising = 0;
491 	phy->address = address;
492 	phy->speed = SPEED_10;
493 	phy->duplex = DUPLEX_HALF;
494 	phy->pause = phy->asym_pause = 0;
495 
496 	/* Take PHY out of isolate mode and reset it. */
497 	if (emac_mii_reset_phy(phy))
498 		return -ENODEV;
499 
500 	/* Read ID and find matching entry */
501 	id = (phy_read(phy, MII_PHYSID1) << 16) | phy_read(phy, MII_PHYSID2);
502 	for (i = 0; (def = mii_phy_table[i]) != NULL; i++)
503 		if ((id & def->phy_id_mask) == def->phy_id)
504 			break;
505 	/* Should never be NULL (we have a generic entry), but... */
506 	if (!def)
507 		return -ENODEV;
508 
509 	phy->def = def;
510 
511 	/* Determine PHY features if needed */
512 	phy->features = def->features;
513 	if (!phy->features) {
514 		u16 bmsr = phy_read(phy, MII_BMSR);
515 		if (bmsr & BMSR_ANEGCAPABLE)
516 			phy->features |= SUPPORTED_Autoneg;
517 		if (bmsr & BMSR_10HALF)
518 			phy->features |= SUPPORTED_10baseT_Half;
519 		if (bmsr & BMSR_10FULL)
520 			phy->features |= SUPPORTED_10baseT_Full;
521 		if (bmsr & BMSR_100HALF)
522 			phy->features |= SUPPORTED_100baseT_Half;
523 		if (bmsr & BMSR_100FULL)
524 			phy->features |= SUPPORTED_100baseT_Full;
525 		if (bmsr & BMSR_ESTATEN) {
526 			u16 esr = phy_read(phy, MII_ESTATUS);
527 			if (esr & ESTATUS_1000_TFULL)
528 				phy->features |= SUPPORTED_1000baseT_Full;
529 			if (esr & ESTATUS_1000_THALF)
530 				phy->features |= SUPPORTED_1000baseT_Half;
531 		}
532 		phy->features |= SUPPORTED_MII;
533 	}
534 
535 	/* Setup default advertising */
536 	phy->advertising = phy->features;
537 
538 	return 0;
539 }
540 
541 MODULE_LICENSE("GPL");
542