[go: nahoru, domu]

11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PHY drivers for the sungem ethernet driver.
36aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file could be shared with other drivers.
56aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik *
663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt * (c) 2002-2007, Benjamin Herrenscmidt (benh@kernel.crashing.org)
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * TODO:
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  - Add support for PHYs that provide an IRQ line
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  - Eventually moved the entire polling state machine in
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    there (out of the eth driver), so that it can easily be
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    skipped on PHYs that implement it in hardware.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  - On LXT971 & BCM5201, Apple uses some chip specific regs
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    to read the link status. Figure out why and if it makes
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    sense to do the same (magic aneg ?)
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  - Apple has some additional power management code for some
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    Broadcom PHYs that they "hide" from the OpenSource version
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    of darwin, still need to reverse engineer that
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mii.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ethtool.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
323c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt#ifdef CONFIG_PPC_PMAC
333c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt#include <asm/prom.h>
343c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt#endif
353c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt
36ef37d38a1fe78ba627b8178af02df31e59b18896Stephen Rothwell#include <linux/sungem_phy.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Link modes of the BCM5400 PHY */
39f71e130966ba429dbd24be08ddbcdf263df9a5adArjan van de Venstatic const int phy_BCM5400_link_table[8][3] = {
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0, 0, 0 },	/* No link */
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0, 0, 0 },	/* 10BT Half Duplex */
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 1, 0, 0 },	/* 10BT Full Duplex */
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0, 1, 0 },	/* 100BT Half Duplex */
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0, 1, 0 },	/* 100BT Half Duplex */
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 1, 1, 0 },	/* 100BT Full Duplex*/
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 1, 0, 1 },	/* 1000BT */
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 1, 0, 1 },	/* 1000BT */
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50abc4da4503bf6cb1864454b464c52959241239bdDavid S. Millerstatic inline int __sungem_phy_read(struct mii_phy* phy, int id, int reg)
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return phy->mdio_read(phy->dev, id, reg);
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55abc4da4503bf6cb1864454b464c52959241239bdDavid S. Millerstatic inline void __sungem_phy_write(struct mii_phy* phy, int id, int reg, int val)
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->mdio_write(phy->dev, id, reg, val);
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
60abc4da4503bf6cb1864454b464c52959241239bdDavid S. Millerstatic inline int sungem_phy_read(struct mii_phy* phy, int reg)
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return phy->mdio_read(phy->dev, phy->mii_id, reg);
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
65abc4da4503bf6cb1864454b464c52959241239bdDavid S. Millerstatic inline void sungem_phy_write(struct mii_phy* phy, int reg, int val)
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->mdio_write(phy->dev, phy->mii_id, reg, val);
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 val;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int limit = 10000;
746aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
75abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	val = __sungem_phy_read(phy, phy_id, MII_BMCR);
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val &= ~(BMCR_ISOLATE | BMCR_PDOWN);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val |= BMCR_RESET;
78abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	__sungem_phy_write(phy, phy_id, MII_BMCR, val);
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(100);
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
82ff01b9163655ace76b29b7ff2f56b25c32f795daRoel Kluin	while (--limit) {
83abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		val = __sungem_phy_read(phy, phy_id, MII_BMCR);
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((val & BMCR_RESET) == 0)
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(10);
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((val & BMCR_ISOLATE) && limit > 0)
89abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		__sungem_phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE);
906aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
91807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return limit <= 0;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm5201_init(struct mii_phy* phy)
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 data;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
98abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5201_MULTIPHY);
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
100abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5201_MULTIPHY, data);
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
102abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5201_INTERRUPT, 0);
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm5201_suspend(struct mii_phy* phy)
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
109abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5201_INTERRUPT, 0);
110abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm5221_init(struct mii_phy* phy)
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 data;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
119abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5221_TEST);
120abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5221_TEST,
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
123abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
124abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
127abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
128abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data | MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR);
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5221_TEST);
132abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5221_TEST,
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm5221_suspend(struct mii_phy* phy)
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 data;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
142abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5221_TEST);
143abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5221_TEST,
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
146abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
147abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  data | MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE);
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidtstatic int bcm5241_init(struct mii_phy* phy)
15463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt{
15563ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	u16 data;
15663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
157abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5221_TEST);
158abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5221_TEST,
15963ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
16063ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
161abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2);
162abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2,
16363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		data | MII_BCM5221_SHDOW_AUX_STAT2_APD);
16463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
165abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
166abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
16763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		data & ~MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR);
16863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
169abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5221_TEST);
170abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5221_TEST,
17163ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		data & ~MII_BCM5221_TEST_ENABLE_SHADOWS);
17263ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
17363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	return 0;
17463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt}
17563ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
17663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidtstatic int bcm5241_suspend(struct mii_phy* phy)
17763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt{
17863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	u16 data;
17963ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
180abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5221_TEST);
181abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5221_TEST,
18263ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
18363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
184abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
185abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
18663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		  data | MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR);
18763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
18863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	return 0;
18963ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt}
19063ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm5400_init(struct mii_phy* phy)
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 data;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Configure for gigabit full duplex */
196abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5400_AUXCONTROL);
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data |= MII_BCM5400_AUXCONTROL_PWR10BASET;
198abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5400_AUXCONTROL, data);
1996aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
200abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5400_GB_CONTROL);
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
202abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5400_GB_CONTROL, data);
2036aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(100);
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Reset and configure cascaded 10/100 PHY */
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(void)reset_one_mii_phy(phy, 0x1f);
2086aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
209abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = __sungem_phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
211abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	__sungem_phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
213abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5400_AUXCONTROL);
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
215abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5400_AUXCONTROL, data);
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm5400_suspend(struct mii_phy* phy)
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
223abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, BMCR_PDOWN);
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm5401_init(struct mii_phy* phy)
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 data;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rev;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
233abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	rev = sungem_phy_read(phy, MII_PHYSID2) & 0x000f;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rev == 0 || rev == 3) {
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Some revisions of 5401 appear to need this
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * initialisation sequence to disable, according
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * to OF, "tap power management"
2386aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik		 *
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * WARNING ! OF and Darwin don't agree on the
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * register addresses. OF seem to interpret the
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * register numbers below as decimal
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Note: This should (and does) match tg3_init_5401phy_dsp
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *       in the tg3.c driver. -DaveM
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
246abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x18, 0x0c20);
247abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x17, 0x0012);
248abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x15, 0x1804);
249abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x17, 0x0013);
250abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x15, 0x1204);
251abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x17, 0x8006);
252abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x15, 0x0132);
253abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x17, 0x8006);
254abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x15, 0x0232);
255abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x17, 0x201f);
256abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x15, 0x0a20);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2586aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Configure for gigabit full duplex */
260abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5400_GB_CONTROL);
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
262abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5400_GB_CONTROL, data);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(10);
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Reset and configure cascaded 10/100 PHY */
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(void)reset_one_mii_phy(phy, 0x1f);
2686aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
269abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = __sungem_phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
271abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	__sungem_phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data);
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm5401_suspend(struct mii_phy* phy)
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
279abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, BMCR_PDOWN);
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm5411_init(struct mii_phy* phy)
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 data;
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Here's some more Apple black magic to setup
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * some voltage stuffs.
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
291abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, 0x1c, 0x8c23);
292abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, 0x1c, 0x8ca3);
293abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, 0x1c, 0x8c23);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Here, Apple seems to want to reset it, do
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * it as well
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
298abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, BMCR_RESET);
299abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, 0x1340);
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	data = sungem_phy_read(phy, MII_BCM5400_GB_CONTROL);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
303abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BCM5400_GB_CONTROL, data);
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(10);
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Reset and configure cascaded 10/100 PHY */
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(void)reset_one_mii_phy(phy, 0x1f);
3096aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
313eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkampstatic int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
314eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp{
315eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	u16 ctl, adv;
316eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
317eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->autoneg = 1;
318eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->speed = SPEED_10;
319eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->duplex = DUPLEX_HALF;
320eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->pause = 0;
321eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->advertising = advertise;
322eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
323eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	/* Setup standard advertise */
324abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	adv = sungem_phy_read(phy, MII_ADVERTISE);
325eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
326eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if (advertise & ADVERTISED_10baseT_Half)
327eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		adv |= ADVERTISE_10HALF;
328eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if (advertise & ADVERTISED_10baseT_Full)
329eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		adv |= ADVERTISE_10FULL;
330eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if (advertise & ADVERTISED_100baseT_Half)
331eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		adv |= ADVERTISE_100HALF;
332eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if (advertise & ADVERTISED_100baseT_Full)
333eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		adv |= ADVERTISE_100FULL;
334abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_ADVERTISE, adv);
335eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
336eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	/* Start/Restart aneg */
337abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	ctl = sungem_phy_read(phy, MII_BMCR);
338eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
339abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, ctl);
340eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
341eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	return 0;
342eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp}
343eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
344eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkampstatic int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
345eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp{
346eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	u16 ctl;
347eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
348eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->autoneg = 0;
349eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->speed = speed;
350eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->duplex = fd;
351eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->pause = 0;
352eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
353abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	ctl = sungem_phy_read(phy, MII_BMCR);
354eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE);
355eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
356eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	/* First reset the PHY */
357abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
358eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
359eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	/* Select speed & duplex */
360eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	switch(speed) {
361eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	case SPEED_10:
362eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		break;
363eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	case SPEED_100:
364eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		ctl |= BMCR_SPEED100;
365eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		break;
366eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	case SPEED_1000:
367eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	default:
368eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		return -EINVAL;
369eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	}
370eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if (fd == DUPLEX_FULL)
371eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		ctl |= BMCR_FULLDPLX;
372abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, ctl);
373eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
374eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	return 0;
375eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp}
376eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
377eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkampstatic int genmii_poll_link(struct mii_phy *phy)
378eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp{
379eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	u16 status;
380eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
381abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	(void)sungem_phy_read(phy, MII_BMSR);
382abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	status = sungem_phy_read(phy, MII_BMSR);
383eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if ((status & BMSR_LSTATUS) == 0)
384eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		return 0;
385eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE))
386eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		return 0;
387eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	return 1;
388eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp}
389eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
390eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkampstatic int genmii_read_link(struct mii_phy *phy)
391eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp{
392eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	u16 lpa;
393eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
394eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if (phy->autoneg) {
395abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		lpa = sungem_phy_read(phy, MII_LPA);
396eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
397eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		if (lpa & (LPA_10FULL | LPA_100FULL))
398eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp			phy->duplex = DUPLEX_FULL;
399eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		else
400eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp			phy->duplex = DUPLEX_HALF;
401eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		if (lpa & (LPA_100FULL | LPA_100HALF))
402eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp			phy->speed = SPEED_100;
403eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		else
404eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp			phy->speed = SPEED_10;
405eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		phy->pause = 0;
406eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	}
407eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	/* On non-aneg, we assume what we put in BMCR is the speed,
408eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	 * though magic-aneg shouldn't prevent this case from occurring
409eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	 */
410eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
411eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	 return 0;
412eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp}
413eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
414d47f3640fe2ac4da8a8e713a549e6eaf23ac2084Johannes Bergstatic int generic_suspend(struct mii_phy* phy)
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
416abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, BMCR_PDOWN);
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm5421_init(struct mii_phy* phy)
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 data;
4243c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	unsigned int id;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
426abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	id = (sungem_phy_read(phy, MII_PHYSID1) << 16 | sungem_phy_read(phy, MII_PHYSID2));
4273c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt
4283c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	/* Revision 0 of 5421 needs some fixups */
4293c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	if (id == 0x002060e0) {
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* This is borrowed from MacOS
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
432abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x18, 0x1007);
433abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		data = sungem_phy_read(phy, 0x18);
434abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x18, data | 0x0400);
435abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x18, 0x0007);
436abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		data = sungem_phy_read(phy, 0x18);
437abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x18, data | 0x0800);
438abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x17, 0x000a);
439abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		data = sungem_phy_read(phy, 0x15);
440abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x15, data | 0x0200);
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4433c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	/* Pick up some init code from OF for K2 version */
4443c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	if ((id & 0xfffffff0) == 0x002062e0) {
445abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 4, 0x01e1);
446abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 9, 0x0300);
4473c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	}
4483c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt
4493c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	/* Check if we can enable automatic low power */
4503c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt#ifdef CONFIG_PPC_PMAC
4513c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	if (phy->platform_data) {
4523c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt		struct device_node *np = of_get_parent(phy->platform_data);
4533c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt		int can_low_power = 1;
45440cd3a4564ed6b7bc0279430120ca0e9b83cf486Stephen Rothwell		if (np == NULL || of_get_property(np, "no-autolowpower", NULL))
4553c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt			can_low_power = 0;
4563c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt		if (can_low_power) {
4573c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt			/* Enable automatic low-power */
458abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller			sungem_phy_write(phy, 0x1c, 0x9002);
459abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller			sungem_phy_write(phy, 0x1c, 0xa821);
460abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller			sungem_phy_write(phy, 0x1c, 0x941d);
4613c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt		}
4623c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	}
4633c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt#endif /* CONFIG_PPC_PMAC */
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise)
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 ctl, adv;
4716aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->autoneg = 1;
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->speed = SPEED_10;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->duplex = DUPLEX_HALF;
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->pause = 0;
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->advertising = advertise;
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Setup standard advertise */
479abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	adv = sungem_phy_read(phy, MII_ADVERTISE);
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (advertise & ADVERTISED_10baseT_Half)
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adv |= ADVERTISE_10HALF;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (advertise & ADVERTISED_10baseT_Full)
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adv |= ADVERTISE_10FULL;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (advertise & ADVERTISED_100baseT_Half)
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adv |= ADVERTISE_100HALF;
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (advertise & ADVERTISED_100baseT_Full)
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adv |= ADVERTISE_100FULL;
48963ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	if (advertise & ADVERTISED_Pause)
49063ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		adv |= ADVERTISE_PAUSE_CAP;
49163ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	if (advertise & ADVERTISED_Asym_Pause)
49263ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		adv |= ADVERTISE_PAUSE_ASYM;
493abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_ADVERTISE, adv);
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Setup 1000BT advertise */
496abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	adv = sungem_phy_read(phy, MII_1000BASETCONTROL);
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP);
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (advertise & SUPPORTED_1000baseT_Half)
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (advertise & SUPPORTED_1000baseT_Full)
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
502abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_1000BASETCONTROL, adv);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start/Restart aneg */
505abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	ctl = sungem_phy_read(phy, MII_BMCR);
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
507abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, ctl);
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd)
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 ctl;
5156aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->autoneg = 0;
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->speed = speed;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->duplex = fd;
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->pause = 0;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	ctl = sungem_phy_read(phy, MII_BMCR);
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* First reset the PHY */
525abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Select speed & duplex */
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(speed) {
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SPEED_10:
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SPEED_100:
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ctl |= BMCR_SPEED100;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SPEED_1000:
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ctl |= BMCR_SPD2;
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fd == DUPLEX_FULL)
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ctl |= BMCR_FULLDPLX;
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// XXX Should we set the sungem to GII now on 1000BT ?
5416aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
542abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, ctl);
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bcm54xx_read_link(struct mii_phy *phy)
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5496aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik	int link_mode;
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 val;
5516aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (phy->autoneg) {
553abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	    	val = sungem_phy_read(phy, MII_BCM5400_AUXSTATUS);
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >>
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT);
55663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		phy->duplex = phy_BCM5400_link_table[link_mode][0] ?
55763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt			DUPLEX_FULL : DUPLEX_HALF;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		phy->speed = phy_BCM5400_link_table[link_mode][2] ?
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				SPEED_1000 :
56063ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt				(phy_BCM5400_link_table[link_mode][1] ?
56163ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt				 SPEED_100 : SPEED_10);
562abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		val = sungem_phy_read(phy, MII_LPA);
56363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		phy->pause = (phy->duplex == DUPLEX_FULL) &&
56463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt			((val & LPA_PAUSE) != 0);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* On non-aneg, we assume what we put in BMCR is the speed,
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * though magic-aneg shouldn't prevent this case from occurring
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
57363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidtstatic int marvell88e1111_init(struct mii_phy* phy)
57463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt{
57563ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	u16 rev;
57663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
57763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	/* magic init sequence for rev 0 */
578abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	rev = sungem_phy_read(phy, MII_PHYSID2) & 0x000f;
57963ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	if (rev == 0) {
580abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x1d, 0x000a);
581abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x1e, 0x0821);
58263ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
583abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x1d, 0x0006);
584abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x1e, 0x8600);
58563ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
586abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x1d, 0x000b);
587abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x1e, 0x0100);
58863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
589abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x1d, 0x0004);
590abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x1e, 0x4850);
59163ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	}
59263ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	return 0;
59363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt}
59463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
595eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp#define BCM5421_MODE_MASK	(1 << 5)
596eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
597eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkampstatic int bcm5421_poll_link(struct mii_phy* phy)
598eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp{
599eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	u32 phy_reg;
600eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	int mode;
601eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
602eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	/* find out in what mode we are */
603abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_NCONFIG, 0x1000);
604abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	phy_reg = sungem_phy_read(phy, MII_NCONFIG);
605eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
606eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	mode = (phy_reg & BCM5421_MODE_MASK) >> 5;
607eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
608eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if ( mode == BCM54XX_COPPER)
609eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		return genmii_poll_link(phy);
610eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
61148fc7f7e787dd65ffe88521bce31f4062ba273ebAdam Buchbinder	/* try to find out whether we have a link */
612abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_NCONFIG, 0x2000);
613abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	phy_reg = sungem_phy_read(phy, MII_NCONFIG);
614eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
615eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if (phy_reg & 0x0020)
616eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		return 0;
617eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	else
618eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		return 1;
619eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp}
620eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
621eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkampstatic int bcm5421_read_link(struct mii_phy* phy)
622eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp{
623eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	u32 phy_reg;
624eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	int mode;
625eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
626eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	/* find out in what mode we are */
627abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_NCONFIG, 0x1000);
628abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	phy_reg = sungem_phy_read(phy, MII_NCONFIG);
629eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
630eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	mode = (phy_reg & BCM5421_MODE_MASK ) >> 5;
631eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
632eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if ( mode == BCM54XX_COPPER)
633eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		return bcm54xx_read_link(phy);
634eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
635eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->speed = SPEED_1000;
636eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
63748fc7f7e787dd65ffe88521bce31f4062ba273ebAdam Buchbinder	/* find out whether we are running half- or full duplex */
638abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_NCONFIG, 0x2000);
639abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	phy_reg = sungem_phy_read(phy, MII_NCONFIG);
640eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
641eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if ( (phy_reg & 0x0080) >> 7)
642eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		phy->duplex |=  DUPLEX_HALF;
643eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	else
644eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		phy->duplex |=  DUPLEX_FULL;
645eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
646eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	return 0;
647eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp}
648eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
649eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkampstatic int bcm5421_enable_fiber(struct mii_phy* phy, int autoneg)
650eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp{
651eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	/* enable fiber mode */
652abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_NCONFIG, 0x9020);
653eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	/* LEDs active in both modes, autosense prio = fiber */
654abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_NCONFIG, 0x945f);
655eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
656eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if (!autoneg) {
657eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		/* switch off fibre autoneg */
658abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, MII_NCONFIG, 0xfc01);
659abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, 0x0b, 0x0004);
660eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	}
661eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
662eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->autoneg = autoneg;
663eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
664eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	return 0;
665eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp}
666eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
667eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp#define BCM5461_FIBER_LINK	(1 << 2)
668eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp#define BCM5461_MODE_MASK	(3 << 1)
669eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
670eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkampstatic int bcm5461_poll_link(struct mii_phy* phy)
671eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp{
672eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	u32 phy_reg;
673eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	int mode;
674eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
675eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	/* find out in what mode we are */
676abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_NCONFIG, 0x7c00);
677abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	phy_reg = sungem_phy_read(phy, MII_NCONFIG);
678eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
679eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	mode = (phy_reg & BCM5461_MODE_MASK ) >> 1;
680eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
681eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if ( mode == BCM54XX_COPPER)
682eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		return genmii_poll_link(phy);
683eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
68448fc7f7e787dd65ffe88521bce31f4062ba273ebAdam Buchbinder	/* find out whether we have a link */
685abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_NCONFIG, 0x7000);
686abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	phy_reg = sungem_phy_read(phy, MII_NCONFIG);
687eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
688eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if (phy_reg & BCM5461_FIBER_LINK)
689eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		return 1;
690eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	else
691eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		return 0;
692eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp}
693eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
694eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp#define BCM5461_FIBER_DUPLEX	(1 << 3)
695eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
696eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkampstatic int bcm5461_read_link(struct mii_phy* phy)
697eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp{
698eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	u32 phy_reg;
699eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	int mode;
700eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
701eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	/* find out in what mode we are */
702abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_NCONFIG, 0x7c00);
703abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	phy_reg = sungem_phy_read(phy, MII_NCONFIG);
704eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
705eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	mode = (phy_reg & BCM5461_MODE_MASK ) >> 1;
706eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
707eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if ( mode == BCM54XX_COPPER) {
708eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		return bcm54xx_read_link(phy);
709eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	}
710eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
711eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->speed = SPEED_1000;
712eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
71348fc7f7e787dd65ffe88521bce31f4062ba273ebAdam Buchbinder	/* find out whether we are running half- or full duplex */
714abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_NCONFIG, 0x7000);
715abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	phy_reg = sungem_phy_read(phy, MII_NCONFIG);
716eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
717eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if (phy_reg & BCM5461_FIBER_DUPLEX)
718eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		phy->duplex |=  DUPLEX_FULL;
719eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	else
720eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		phy->duplex |=  DUPLEX_HALF;
721eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
722eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	return 0;
723eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp}
724eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
725eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkampstatic int bcm5461_enable_fiber(struct mii_phy* phy, int autoneg)
726eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp{
727eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	/* select fiber mode, enable 1000 base-X registers */
728abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_NCONFIG, 0xfc0b);
729eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
730eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	if (autoneg) {
731eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		/* enable fiber with no autonegotiation */
732abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, MII_ADVERTISE, 0x01e0);
733abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, MII_BMCR, 0x1140);
734eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	} else {
735eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp		/* enable fiber with autonegotiation */
736abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		sungem_phy_write(phy, MII_BMCR, 0x0140);
737eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	}
738eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
739eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	phy->autoneg = autoneg;
740eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
741eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	return 0;
742eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp}
743eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int marvell_setup_aneg(struct mii_phy *phy, u32 advertise)
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 ctl, adv;
7476aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->autoneg = 1;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->speed = SPEED_10;
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->duplex = DUPLEX_HALF;
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->pause = 0;
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->advertising = advertise;
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Setup standard advertise */
755abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	adv = sungem_phy_read(phy, MII_ADVERTISE);
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (advertise & ADVERTISED_10baseT_Half)
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adv |= ADVERTISE_10HALF;
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (advertise & ADVERTISED_10baseT_Full)
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adv |= ADVERTISE_10FULL;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (advertise & ADVERTISED_100baseT_Half)
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adv |= ADVERTISE_100HALF;
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (advertise & ADVERTISED_100baseT_Full)
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adv |= ADVERTISE_100FULL;
76563ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	if (advertise & ADVERTISED_Pause)
76663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		adv |= ADVERTISE_PAUSE_CAP;
76763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	if (advertise & ADVERTISED_Asym_Pause)
76863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		adv |= ADVERTISE_PAUSE_ASYM;
769abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_ADVERTISE, adv);
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Setup 1000BT advertise & enable crossover detect
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * XXX How do we advertise 1000BT ? Darwin source is
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * confusing here, they read from specific control and
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * write to control... Someone has specs for those
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * beasts ?
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
777abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	adv = sungem_phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX;
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MII_1000BASETCONTROL_HALFDUPLEXCAP);
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (advertise & SUPPORTED_1000baseT_Half)
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (advertise & SUPPORTED_1000baseT_Full)
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
785abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_1000BASETCONTROL, adv);
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Start/Restart aneg */
788abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	ctl = sungem_phy_read(phy, MII_BMCR);
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
790abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, ctl);
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int marvell_setup_forced(struct mii_phy *phy, int speed, int fd)
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 ctl, ctl2;
7986aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->autoneg = 0;
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->speed = speed;
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->duplex = fd;
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->pause = 0;
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
804abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	ctl = sungem_phy_read(phy, MII_BMCR);
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE);
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctl |= BMCR_RESET;
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Select speed & duplex */
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(speed) {
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SPEED_10:
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SPEED_100:
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ctl |= BMCR_SPEED100;
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* I'm not sure about the one below, again, Darwin source is
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * quite confusing and I lack chip specs
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SPEED_1000:
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ctl |= BMCR_SPD2;
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fd == DUPLEX_FULL)
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ctl |= BMCR_FULLDPLX;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Disable crossover. Again, the way Apple does it is strange,
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * though I don't assume they are wrong ;)
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
827abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	ctl2 = sungem_phy_read(phy, MII_M1011_PHY_SPEC_CONTROL);
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX |
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX |
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MII_1000BASETCONTROL_FULLDUPLEXCAP |
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MII_1000BASETCONTROL_HALFDUPLEXCAP);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (speed == SPEED_1000)
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ctl2 |= (fd == DUPLEX_FULL) ?
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MII_1000BASETCONTROL_FULLDUPLEXCAP :
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MII_1000BASETCONTROL_HALFDUPLEXCAP;
836abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_1000BASETCONTROL, ctl2);
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	// XXX Should we set the sungem to GII now on 1000BT ?
8396aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
840abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	sungem_phy_write(phy, MII_BMCR, ctl);
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int marvell_read_link(struct mii_phy *phy)
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
84763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	u16 status, pmask;
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (phy->autoneg) {
850abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller		status = sungem_phy_read(phy, MII_M1011_PHY_SPEC_STATUS);
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EAGAIN;
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status & MII_M1011_PHY_SPEC_STATUS_1000)
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			phy->speed = SPEED_1000;
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else if (status & MII_M1011_PHY_SPEC_STATUS_100)
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			phy->speed = SPEED_100;
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			phy->speed = SPEED_10;
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			phy->duplex = DUPLEX_FULL;
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			phy->duplex = DUPLEX_HALF;
86363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		pmask = MII_M1011_PHY_SPEC_STATUS_TX_PAUSE |
86463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt			MII_M1011_PHY_SPEC_STATUS_RX_PAUSE;
86563ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt		phy->pause = (status & pmask) == pmask;
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* On non-aneg, we assume what we put in BMCR is the speed,
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * though magic-aneg shouldn't prevent this case from occurring
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
87463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt#define MII_BASIC_FEATURES \
87563ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |	\
87663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |	\
87763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	 SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII |	\
87863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	 SUPPORTED_Pause)
87963ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
88063ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt/* On gigabit capable PHYs, we advertise Pause support but not asym pause
88163ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt * support for now as I'm not sure it's supported and Darwin doesn't do
88263ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt * it neither. --BenH.
88363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt */
88463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt#define MII_GBIT_FEATURES \
88563ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	(MII_BASIC_FEATURES |	\
88663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full)
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Broadcom BCM 5201 */
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_ops bcm5201_phy_ops = {
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init		= bcm5201_init,
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= bcm5201_suspend,
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_aneg	= genmii_setup_aneg,
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_forced	= genmii_setup_forced,
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.poll_link	= genmii_poll_link,
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_link	= genmii_read_link,
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_def bcm5201_phy_def = {
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id		= 0x00406210,
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id_mask	= 0xfffffff0,
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "BCM5201",
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.features	= MII_BASIC_FEATURES,
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.magic_aneg	= 1,
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ops		= &bcm5201_phy_ops
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Broadcom BCM 5221 */
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_ops bcm5221_phy_ops = {
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= bcm5221_suspend,
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init		= bcm5221_init,
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_aneg	= genmii_setup_aneg,
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_forced	= genmii_setup_forced,
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.poll_link	= genmii_poll_link,
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_link	= genmii_read_link,
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_def bcm5221_phy_def = {
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id		= 0x004061e0,
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id_mask	= 0xfffffff0,
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "BCM5221",
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.features	= MII_BASIC_FEATURES,
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.magic_aneg	= 1,
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ops		= &bcm5221_phy_ops
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
92663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt/* Broadcom BCM 5241 */
92763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidtstatic struct mii_phy_ops bcm5241_phy_ops = {
92863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.suspend	= bcm5241_suspend,
92963ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.init		= bcm5241_init,
93063ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.setup_aneg	= genmii_setup_aneg,
93163ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.setup_forced	= genmii_setup_forced,
93263ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.poll_link	= genmii_poll_link,
93363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.read_link	= genmii_read_link,
93463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt};
93563ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidtstatic struct mii_phy_def bcm5241_phy_def = {
93663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.phy_id		= 0x0143bc30,
93763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.phy_id_mask	= 0xfffffff0,
93863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.name		= "BCM5241",
93963ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.features	= MII_BASIC_FEATURES,
94063ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.magic_aneg	= 1,
94163ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.ops		= &bcm5241_phy_ops
94263ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt};
94363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Broadcom BCM 5400 */
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_ops bcm5400_phy_ops = {
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init		= bcm5400_init,
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= bcm5400_suspend,
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_aneg	= bcm54xx_setup_aneg,
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_forced	= bcm54xx_setup_forced,
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.poll_link	= genmii_poll_link,
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_link	= bcm54xx_read_link,
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_def bcm5400_phy_def = {
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id		= 0x00206040,
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id_mask	= 0xfffffff0,
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "BCM5400",
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.features	= MII_GBIT_FEATURES,
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.magic_aneg	= 1,
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ops		= &bcm5400_phy_ops
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Broadcom BCM 5401 */
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_ops bcm5401_phy_ops = {
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init		= bcm5401_init,
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= bcm5401_suspend,
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_aneg	= bcm54xx_setup_aneg,
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_forced	= bcm54xx_setup_forced,
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.poll_link	= genmii_poll_link,
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_link	= bcm54xx_read_link,
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_def bcm5401_phy_def = {
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id		= 0x00206050,
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id_mask	= 0xfffffff0,
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "BCM5401",
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.features	= MII_GBIT_FEATURES,
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.magic_aneg	= 1,
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ops		= &bcm5401_phy_ops
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Broadcom BCM 5411 */
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_ops bcm5411_phy_ops = {
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init		= bcm5411_init,
985d47f3640fe2ac4da8a8e713a549e6eaf23ac2084Johannes Berg	.suspend	= generic_suspend,
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_aneg	= bcm54xx_setup_aneg,
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_forced	= bcm54xx_setup_forced,
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.poll_link	= genmii_poll_link,
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_link	= bcm54xx_read_link,
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_def bcm5411_phy_def = {
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id		= 0x00206070,
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id_mask	= 0xfffffff0,
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "BCM5411",
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.features	= MII_GBIT_FEATURES,
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.magic_aneg	= 1,
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ops		= &bcm5411_phy_ops
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Broadcom BCM 5421 */
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_ops bcm5421_phy_ops = {
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init		= bcm5421_init,
1004d47f3640fe2ac4da8a8e713a549e6eaf23ac2084Johannes Berg	.suspend	= generic_suspend,
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_aneg	= bcm54xx_setup_aneg,
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_forced	= bcm54xx_setup_forced,
1007eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	.poll_link	= bcm5421_poll_link,
1008eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	.read_link	= bcm5421_read_link,
10098ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	.enable_fiber   = bcm5421_enable_fiber,
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_def bcm5421_phy_def = {
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id		= 0x002060e0,
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id_mask	= 0xfffffff0,
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "BCM5421",
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.features	= MII_GBIT_FEATURES,
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.magic_aneg	= 1,
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ops		= &bcm5421_phy_ops
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Broadcom BCM 5421 built-in K2 */
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_ops bcm5421k2_phy_ops = {
10233c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	.init		= bcm5421_init,
1024d47f3640fe2ac4da8a8e713a549e6eaf23ac2084Johannes Berg	.suspend	= generic_suspend,
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_aneg	= bcm54xx_setup_aneg,
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_forced	= bcm54xx_setup_forced,
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.poll_link	= genmii_poll_link,
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_link	= bcm54xx_read_link,
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_def bcm5421k2_phy_def = {
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id		= 0x002062e0,
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id_mask	= 0xfffffff0,
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "BCM5421-K2",
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.features	= MII_GBIT_FEATURES,
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.magic_aneg	= 1,
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ops		= &bcm5421k2_phy_ops
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10408ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkampstatic struct mii_phy_ops bcm5461_phy_ops = {
10418ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	.init		= bcm5421_init,
10428ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	.suspend	= generic_suspend,
10438ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	.setup_aneg	= bcm54xx_setup_aneg,
10448ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	.setup_forced	= bcm54xx_setup_forced,
1045eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	.poll_link	= bcm5461_poll_link,
1046eb5b5b2ff96e8f3a42a46378968a166bb56bd900Jens Osterkamp	.read_link	= bcm5461_read_link,
10478ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	.enable_fiber   = bcm5461_enable_fiber,
10488ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp};
10498ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp
10508ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkampstatic struct mii_phy_def bcm5461_phy_def = {
10518ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	.phy_id		= 0x002060c0,
10528ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	.phy_id_mask	= 0xfffffff0,
10538ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	.name		= "BCM5461",
10548ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	.features	= MII_GBIT_FEATURES,
10558ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	.magic_aneg	= 1,
10568ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	.ops		= &bcm5461_phy_ops
10578ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp};
10588ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp
10593c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt/* Broadcom BCM 5462 built-in Vesta */
10603c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidtstatic struct mii_phy_ops bcm5462V_phy_ops = {
10613c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	.init		= bcm5421_init,
1062d47f3640fe2ac4da8a8e713a549e6eaf23ac2084Johannes Berg	.suspend	= generic_suspend,
10633c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	.setup_aneg	= bcm54xx_setup_aneg,
10643c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	.setup_forced	= bcm54xx_setup_forced,
10653c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	.poll_link	= genmii_poll_link,
10663c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	.read_link	= bcm54xx_read_link,
10673c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt};
10683c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt
10693c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidtstatic struct mii_phy_def bcm5462V_phy_def = {
10703c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	.phy_id		= 0x002060d0,
10713c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	.phy_id_mask	= 0xfffffff0,
10723c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	.name		= "BCM5462-Vesta",
10733c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	.features	= MII_GBIT_FEATURES,
10743c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	.magic_aneg	= 1,
10753c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	.ops		= &bcm5462V_phy_ops
10763c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt};
10773c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt
107863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt/* Marvell 88E1101 amd 88E1111 */
107963ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidtstatic struct mii_phy_ops marvell88e1101_phy_ops = {
1080d47f3640fe2ac4da8a8e713a549e6eaf23ac2084Johannes Berg	.suspend	= generic_suspend,
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_aneg	= marvell_setup_aneg,
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_forced	= marvell_setup_forced,
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.poll_link	= genmii_poll_link,
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_link	= marvell_read_link
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
108763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidtstatic struct mii_phy_ops marvell88e1111_phy_ops = {
108863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.init		= marvell88e1111_init,
108963ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.suspend	= generic_suspend,
109063ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.setup_aneg	= marvell_setup_aneg,
109163ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.setup_forced	= marvell_setup_forced,
109263ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.poll_link	= genmii_poll_link,
109363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.read_link	= marvell_read_link
109463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt};
109563ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt
109663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt/* two revs in darwin for the 88e1101 ... I could use a datasheet
109763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt * to get the proper names...
109863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt */
109963ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidtstatic struct mii_phy_def marvell88e1101v1_phy_def = {
110063ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.phy_id		= 0x01410c20,
110163ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.phy_id_mask	= 0xfffffff0,
110263ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.name		= "Marvell 88E1101v1",
110363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.features	= MII_GBIT_FEATURES,
110463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.magic_aneg	= 1,
110563ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.ops		= &marvell88e1101_phy_ops
110663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt};
110763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidtstatic struct mii_phy_def marvell88e1101v2_phy_def = {
110863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.phy_id		= 0x01410c60,
110963ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.phy_id_mask	= 0xfffffff0,
111063ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.name		= "Marvell 88E1101v2",
111163ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.features	= MII_GBIT_FEATURES,
111263ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.magic_aneg	= 1,
111363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.ops		= &marvell88e1101_phy_ops
111463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt};
111563ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidtstatic struct mii_phy_def marvell88e1111_phy_def = {
111663ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.phy_id		= 0x01410cc0,
111763ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.phy_id_mask	= 0xfffffff0,
111863ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.name		= "Marvell 88E1111",
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.features	= MII_GBIT_FEATURES,
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.magic_aneg	= 1,
112163ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	.ops		= &marvell88e1111_phy_ops
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Generic implementation for most 10/100 PHYs */
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_ops generic_phy_ops = {
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_aneg	= genmii_setup_aneg,
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setup_forced	= genmii_setup_forced,
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.poll_link	= genmii_poll_link,
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read_link	= genmii_read_link
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_def genmii_phy_def = {
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id		= 0x00000000,
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phy_id_mask	= 0x00000000,
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name		= "Generic MII",
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.features	= MII_BASIC_FEATURES,
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.magic_aneg	= 0,
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.ops		= &generic_phy_ops
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mii_phy_def* mii_phy_table[] = {
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&bcm5201_phy_def,
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&bcm5221_phy_def,
114463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	&bcm5241_phy_def,
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&bcm5400_phy_def,
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&bcm5401_phy_def,
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&bcm5411_phy_def,
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&bcm5421_phy_def,
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&bcm5421k2_phy_def,
11508ec93459655a3618dedec6360bb28d63f0010ef6Jens Osterkamp	&bcm5461_phy_def,
11513c326fe9cb7ae022f7589a6f5781e49ceab82e64Benjamin Herrenschmidt	&bcm5462V_phy_def,
115263ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	&marvell88e1101v1_phy_def,
115363ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	&marvell88e1101v2_phy_def,
115463ea998a26d4e03d390fbe31818cc552994d16fdBenjamin Herrenschmidt	&marvell88e1111_phy_def,
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	&genmii_phy_def,
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	NULL
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
115919e2f6fe9601ca5c846b7163e6d6d00f87b34760David S. Millerint sungem_phy_probe(struct mii_phy *phy, int mii_id)
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc;
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 id;
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mii_phy_def* def;
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We do not reset the mii_phy structure as the driver
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * may re-probe the PHY regulary
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->mii_id = mii_id;
11706aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Take PHY out of isloate mode and reset it. */
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rc = reset_one_mii_phy(phy, mii_id);
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc)
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail;
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11766aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik	/* Read ID and find matching entry */
1177abc4da4503bf6cb1864454b464c52959241239bdDavid S. Miller	id = (sungem_phy_read(phy, MII_PHYSID1) << 16 | sungem_phy_read(phy, MII_PHYSID2));
1178c6c759884b05c7449a19d39c763a7482180e2defJoe Perches	printk(KERN_DEBUG KBUILD_MODNAME ": " "PHY ID: %x, addr: %x\n",
1179c6c759884b05c7449a19d39c763a7482180e2defJoe Perches	       id, mii_id);
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i=0; (def = mii_phy_table[i]) != NULL; i++)
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((id & def->phy_id_mask) == def->phy_id)
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Should never be NULL (we have a generic entry), but... */
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (def == NULL)
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto fail;
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->def = def;
11886aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfail:
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->speed = 0;
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->duplex = 0;
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->pause = 0;
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	phy->advertising = 0;
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENODEV;
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
119819e2f6fe9601ca5c846b7163e6d6d00f87b34760David S. MillerEXPORT_SYMBOL(sungem_phy_probe);
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1200