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