Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

Apr 14-17, 2025
Register
Loading...
v6.8
  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
 35static inline int _phy_read(struct mii_phy *phy, int reg)
 36{
 37	return phy->mdio_read(phy->dev, phy->address, reg);
 38}
 39
 40static 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
 45static 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
 50static 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
 55int 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
 79int 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
110static 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
169static 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
206static 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
220static 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 */
280static 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
287static 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
306static 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
344static 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
352static 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
359static 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
367static 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
380static 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
407static 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
424static 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
432static 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
443static 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
451static 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
459static 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
467static 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
474static 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
484static 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
492static 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
499static 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
510int 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
568MODULE_LICENSE("GPL");
v3.15
 
  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
 34static inline int _phy_read(struct mii_phy *phy, int reg)
 35{
 36	return phy->mdio_read(phy->dev, phy->address, reg);
 37}
 38
 39static 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
 44static 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
 49static 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
 54int 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
 78int 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
109static 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
168static 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
205static 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
219static 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 */
279static 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
286static 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
305static 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
343static 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
351static 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
358static 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
366static 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
379static 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
406static 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
423static 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
431static 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
442static 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
450static 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
458static 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
466static 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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473static 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
483int 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
541MODULE_LICENSE("GPL");