[go: nahoru, domu]

11d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson/*
23396c7823efb3a5b8630388c464e1034ea031cedPaul Gortmaker * drivers/net/ethernet/ibm/emac/phy.c
31d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson *
41d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson * Driver for PowerPC 4xx on-chip ethernet controller, PHY support.
51d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson * Borrowed from sungem_phy.c, though I only kept the generic MII
61d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson * driver for now.
71d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson *
81d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson * This file should be shared with other drivers or eventually
91d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson * merged as the "low level" part of miilib
101d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson *
1117cf803a57c89c5afe6d5299ac9416683c3240ddBenjamin Herrenschmidt * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
1217cf803a57c89c5afe6d5299ac9416683c3240ddBenjamin Herrenschmidt *                <benh@kernel.crashing.org>
1317cf803a57c89c5afe6d5299ac9416683c3240ddBenjamin Herrenschmidt *
1417cf803a57c89c5afe6d5299ac9416683c3240ddBenjamin Herrenschmidt * Based on the arch/ppc version of the driver:
1517cf803a57c89c5afe6d5299ac9416683c3240ddBenjamin Herrenschmidt *
161d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson * (c) 2003, Benjamin Herrenscmidt (benh@kernel.crashing.org)
171d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson * (c) 2004-2005, Eugene Surovegin <ebs@ebshome.net>
181d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson *
191d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson */
201d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#include <linux/module.h>
211d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#include <linux/kernel.h>
221d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#include <linux/types.h>
231d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#include <linux/netdevice.h>
241d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#include <linux/mii.h>
251d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#include <linux/ethtool.h>
261d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#include <linux/delay.h>
271d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
281d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#include "emac.h"
291d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#include "phy.h"
301d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
314157ef1b8779b34581ee8b9dc8f7f95188008ecaShawn Guo#define phy_read _phy_read
324157ef1b8779b34581ee8b9dc8f7f95188008ecaShawn Guo#define phy_write _phy_write
334157ef1b8779b34581ee8b9dc8f7f95188008ecaShawn Guo
344157ef1b8779b34581ee8b9dc8f7f95188008ecaShawn Guostatic inline int _phy_read(struct mii_phy *phy, int reg)
351d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson{
361d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	return phy->mdio_read(phy->dev, phy->address, reg);
371d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson}
381d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
394157ef1b8779b34581ee8b9dc8f7f95188008ecaShawn Guostatic inline void _phy_write(struct mii_phy *phy, int reg, int val)
401d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson{
411d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->mdio_write(phy->dev, phy->address, reg, val);
421d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson}
431d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
449e3cb29497561c846d0e7efc445731764d93c749Victor Gallardostatic inline int gpcs_phy_read(struct mii_phy *phy, int reg)
459e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo{
469e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	return phy->mdio_read(phy->dev, phy->gpcs_address, reg);
479e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo}
489e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
499e3cb29497561c846d0e7efc445731764d93c749Victor Gallardostatic inline void gpcs_phy_write(struct mii_phy *phy, int reg, int val)
509e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo{
519e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	phy->mdio_write(phy->dev, phy->gpcs_address, reg, val);
529e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo}
539e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
541d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibsonint emac_mii_reset_phy(struct mii_phy *phy)
551d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson{
561d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	int val;
571d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	int limit = 10000;
581d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
591d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	val = phy_read(phy, MII_BMCR);
601d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	val &= ~(BMCR_ISOLATE | BMCR_ANENABLE);
611d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	val |= BMCR_RESET;
621d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy_write(phy, MII_BMCR, val);
631d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
641d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	udelay(300);
651d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
6646578a6913e6f5e69229561736b94c18c2e88ae4Roel Kluin	while (--limit) {
671d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		val = phy_read(phy, MII_BMCR);
681d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (val >= 0 && (val & BMCR_RESET) == 0)
691d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			break;
701d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		udelay(10);
711d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	}
721d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if ((val & BMCR_ISOLATE) && limit > 0)
731d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
741d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
751d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	return limit <= 0;
761d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson}
771d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
789e3cb29497561c846d0e7efc445731764d93c749Victor Gallardoint emac_mii_reset_gpcs(struct mii_phy *phy)
799e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo{
809e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	int val;
819e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	int limit = 10000;
829e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
839e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	val = gpcs_phy_read(phy, MII_BMCR);
849e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	val &= ~(BMCR_ISOLATE | BMCR_ANENABLE);
859e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	val |= BMCR_RESET;
869e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	gpcs_phy_write(phy, MII_BMCR, val);
879e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
889e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	udelay(300);
899e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
9046578a6913e6f5e69229561736b94c18c2e88ae4Roel Kluin	while (--limit) {
919e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo		val = gpcs_phy_read(phy, MII_BMCR);
929e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo		if (val >= 0 && (val & BMCR_RESET) == 0)
939e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo			break;
949e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo		udelay(10);
959e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	}
969e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	if ((val & BMCR_ISOLATE) && limit > 0)
979e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo		gpcs_phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
989e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
999e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	if (limit > 0 && phy->mode == PHY_MODE_SGMII) {
1009e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo		/* Configure GPCS interface to recommended setting for SGMII */
1019e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo		gpcs_phy_write(phy, 0x04, 0x8120); /* AsymPause, FDX */
1029e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo		gpcs_phy_write(phy, 0x07, 0x2801); /* msg_pg, toggle */
1039e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo		gpcs_phy_write(phy, 0x00, 0x0140); /* 1Gbps, FDX     */
1049e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	}
1059e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
1069e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	return limit <= 0;
1079e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo}
1089e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
1091d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibsonstatic int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
1101d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson{
1111d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	int ctl, adv;
1121d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
1131d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->autoneg = AUTONEG_ENABLE;
1141d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->speed = SPEED_10;
1151d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->duplex = DUPLEX_HALF;
1161d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->pause = phy->asym_pause = 0;
1171d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->advertising = advertise;
1181d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
1191d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	ctl = phy_read(phy, MII_BMCR);
1201d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (ctl < 0)
1211d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		return ctl;
1221d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
1231d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
1241d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* First clear the PHY */
1251d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy_write(phy, MII_BMCR, ctl);
1261d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
1271d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* Setup standard advertise */
1281d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	adv = phy_read(phy, MII_ADVERTISE);
1291d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (adv < 0)
1301d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		return adv;
1311d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
1321d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		 ADVERTISE_PAUSE_ASYM);
1331d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (advertise & ADVERTISED_10baseT_Half)
1341d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		adv |= ADVERTISE_10HALF;
1351d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (advertise & ADVERTISED_10baseT_Full)
1361d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		adv |= ADVERTISE_10FULL;
1371d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (advertise & ADVERTISED_100baseT_Half)
1381d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		adv |= ADVERTISE_100HALF;
1391d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (advertise & ADVERTISED_100baseT_Full)
1401d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		adv |= ADVERTISE_100FULL;
1411d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (advertise & ADVERTISED_Pause)
1421d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		adv |= ADVERTISE_PAUSE_CAP;
1431d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (advertise & ADVERTISED_Asym_Pause)
1441d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		adv |= ADVERTISE_PAUSE_ASYM;
1451d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy_write(phy, MII_ADVERTISE, adv);
1461d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
1471d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (phy->features &
1481d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	    (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) {
1491d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		adv = phy_read(phy, MII_CTRL1000);
1501d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (adv < 0)
1511d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			return adv;
1521d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
1531d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (advertise & ADVERTISED_1000baseT_Full)
1541d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			adv |= ADVERTISE_1000FULL;
1551d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (advertise & ADVERTISED_1000baseT_Half)
1561d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			adv |= ADVERTISE_1000HALF;
1571d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		phy_write(phy, MII_CTRL1000, adv);
1581d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	}
1591d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
1601d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* Start/Restart aneg */
1611d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	ctl = phy_read(phy, MII_BMCR);
1621d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
1631d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy_write(phy, MII_BMCR, ctl);
1641d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
1651d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	return 0;
1661d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson}
1671d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
1681d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibsonstatic int genmii_setup_forced(struct mii_phy *phy, int speed, int fd)
1691d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson{
1701d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	int ctl;
1711d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
1721d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->autoneg = AUTONEG_DISABLE;
1731d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->speed = speed;
1741d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->duplex = fd;
1751d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->pause = phy->asym_pause = 0;
1761d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
1771d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	ctl = phy_read(phy, MII_BMCR);
1781d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (ctl < 0)
1791d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		return ctl;
1801d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
1811d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
1821d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* First clear the PHY */
1831d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy_write(phy, MII_BMCR, ctl | BMCR_RESET);
1841d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
1851d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* Select speed & duplex */
1861d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	switch (speed) {
1871d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	case SPEED_10:
1881d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		break;
1891d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	case SPEED_100:
1901d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		ctl |= BMCR_SPEED100;
1911d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		break;
1921d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	case SPEED_1000:
1931d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		ctl |= BMCR_SPEED1000;
1941d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		break;
1951d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	default:
1961d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		return -EINVAL;
1971d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	}
1981d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (fd == DUPLEX_FULL)
1991d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		ctl |= BMCR_FULLDPLX;
2001d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy_write(phy, MII_BMCR, ctl);
2011d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2021d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	return 0;
2031d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson}
2041d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2051d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibsonstatic int genmii_poll_link(struct mii_phy *phy)
2061d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson{
2071d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	int status;
2081d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2091d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* Clear latched value with dummy read */
2101d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy_read(phy, MII_BMSR);
2111d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	status = phy_read(phy, MII_BMSR);
2121d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (status < 0 || (status & BMSR_LSTATUS) == 0)
2131d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		return 0;
2141d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (phy->autoneg == AUTONEG_ENABLE && !(status & BMSR_ANEGCOMPLETE))
2151d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		return 0;
2161d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	return 1;
2171d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson}
2181d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2191d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibsonstatic int genmii_read_link(struct mii_phy *phy)
2201d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson{
2211d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (phy->autoneg == AUTONEG_ENABLE) {
2221d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		int glpa = 0;
2231d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		int lpa = phy_read(phy, MII_LPA) & phy_read(phy, MII_ADVERTISE);
2241d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (lpa < 0)
2251d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			return lpa;
2261d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2271d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (phy->features &
2281d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		    (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) {
2291d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			int adv = phy_read(phy, MII_CTRL1000);
2301d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			glpa = phy_read(phy, MII_STAT1000);
2311d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2321d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			if (glpa < 0 || adv < 0)
2331d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson				return adv;
2341d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2351d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			glpa &= adv << 2;
2361d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		}
2371d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2381d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		phy->speed = SPEED_10;
2391d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		phy->duplex = DUPLEX_HALF;
2401d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		phy->pause = phy->asym_pause = 0;
2411d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2421d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (glpa & (LPA_1000FULL | LPA_1000HALF)) {
2431d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->speed = SPEED_1000;
2441d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			if (glpa & LPA_1000FULL)
2451d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson				phy->duplex = DUPLEX_FULL;
2461d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		} else if (lpa & (LPA_100FULL | LPA_100HALF)) {
2471d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->speed = SPEED_100;
2481d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			if (lpa & LPA_100FULL)
2491d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson				phy->duplex = DUPLEX_FULL;
2501d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		} else if (lpa & LPA_10FULL)
2511d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->duplex = DUPLEX_FULL;
2521d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2531d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (phy->duplex == DUPLEX_FULL) {
2541d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
2551d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
2561d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		}
2571d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	} else {
2581d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		int bmcr = phy_read(phy, MII_BMCR);
2591d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (bmcr < 0)
2601d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			return bmcr;
2611d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2621d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (bmcr & BMCR_FULLDPLX)
2631d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->duplex = DUPLEX_FULL;
2641d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		else
2651d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->duplex = DUPLEX_HALF;
2661d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (bmcr & BMCR_SPEED1000)
2671d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->speed = SPEED_1000;
2681d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		else if (bmcr & BMCR_SPEED100)
2691d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->speed = SPEED_100;
2701d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		else
2711d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->speed = SPEED_10;
2721d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2731d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		phy->pause = phy->asym_pause = 0;
2741d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	}
2751d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	return 0;
2761d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson}
2771d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2781d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson/* Generic implementation for most 10/100/1000 PHYs */
2791d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibsonstatic struct mii_phy_ops generic_phy_ops = {
2801d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.setup_aneg	= genmii_setup_aneg,
2811d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.setup_forced	= genmii_setup_forced,
2821d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.poll_link	= genmii_poll_link,
2831d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.read_link	= genmii_read_link
2841d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson};
2851d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2861d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibsonstatic struct mii_phy_def genmii_phy_def = {
2871d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.phy_id		= 0x00000000,
2881d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.phy_id_mask	= 0x00000000,
2891d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.name		= "Generic MII",
2901d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.ops		= &generic_phy_ops
2911d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson};
2921d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
2931d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson/* CIS8201 */
2941d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#define MII_CIS8201_10BTCSR	0x16
2951d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#define  TENBTCSR_ECHO_DISABLE	0x2000
2961d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#define MII_CIS8201_EPCR	0x17
2971d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#define  EPCR_MODE_MASK		0x3000
2981d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#define  EPCR_GMII_MODE		0x0000
2991d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#define  EPCR_RGMII_MODE	0x1000
3001d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#define  EPCR_TBI_MODE		0x2000
3011d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#define  EPCR_RTBI_MODE		0x3000
3021d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#define MII_CIS8201_ACSR	0x1c
3031d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson#define  ACSR_PIN_PRIO_SELECT	0x0004
3041d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
3051d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibsonstatic int cis8201_init(struct mii_phy *phy)
3061d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson{
3071d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	int epcr;
3081d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
3091d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	epcr = phy_read(phy, MII_CIS8201_EPCR);
3101d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (epcr < 0)
3111d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		return epcr;
3121d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
3131d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	epcr &= ~EPCR_MODE_MASK;
3141d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
3151d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	switch (phy->mode) {
3161d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	case PHY_MODE_TBI:
3171d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		epcr |= EPCR_TBI_MODE;
3181d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		break;
3191d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	case PHY_MODE_RTBI:
3201d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		epcr |= EPCR_RTBI_MODE;
3211d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		break;
3221d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	case PHY_MODE_GMII:
3231d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		epcr |= EPCR_GMII_MODE;
3241d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		break;
3251d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	case PHY_MODE_RGMII:
3261d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	default:
3271d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		epcr |= EPCR_RGMII_MODE;
3281d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	}
3291d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
3301d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy_write(phy, MII_CIS8201_EPCR, epcr);
3311d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
3321d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* MII regs override strap pins */
3331d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy_write(phy, MII_CIS8201_ACSR,
3341d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		  phy_read(phy, MII_CIS8201_ACSR) | ACSR_PIN_PRIO_SELECT);
3351d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
3361d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* Disable TX_EN -> CRS echo mode, otherwise 10/HDX doesn't work */
3371d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy_write(phy, MII_CIS8201_10BTCSR,
3381d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		  phy_read(phy, MII_CIS8201_10BTCSR) | TENBTCSR_ECHO_DISABLE);
3391d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
3401d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	return 0;
3411d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson}
3421d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
3431d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibsonstatic struct mii_phy_ops cis8201_phy_ops = {
3441d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.init		= cis8201_init,
3451d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.setup_aneg	= genmii_setup_aneg,
3461d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.setup_forced	= genmii_setup_forced,
3471d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.poll_link	= genmii_poll_link,
3481d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.read_link	= genmii_read_link
3491d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson};
3501d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
3511d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibsonstatic struct mii_phy_def cis8201_phy_def = {
3521d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.phy_id		= 0x000fc410,
3531d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.phy_id_mask	= 0x000ffff0,
3541d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.name		= "CIS8201 Gigabit Ethernet",
3551d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	.ops		= &cis8201_phy_ops
3561d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson};
3571d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
358f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roesestatic struct mii_phy_def bcm5248_phy_def = {
359f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese
360f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.phy_id		= 0x0143bc00,
361f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.phy_id_mask	= 0x0ffffff0,
362f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.name		= "BCM5248 10/100 SMII Ethernet",
363f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.ops		= &generic_phy_ops
364f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese};
365f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese
366f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roesestatic int m88e1111_init(struct mii_phy *phy)
367f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese{
368b39d66a81fb4f5ab555f86a2e49f3714f8369a3dHarvey Harrison	pr_debug("%s: Marvell 88E1111 Ethernet\n", __func__);
369f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	phy_write(phy, 0x14, 0x0ce3);
370f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	phy_write(phy, 0x18, 0x4101);
371f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	phy_write(phy, 0x09, 0x0e00);
372f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	phy_write(phy, 0x04, 0x01e1);
373f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	phy_write(phy, 0x00, 0x9140);
374f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	phy_write(phy, 0x00, 0x1140);
375f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese
376f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	return  0;
377f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese}
378f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese
3799e3cb29497561c846d0e7efc445731764d93c749Victor Gallardostatic int m88e1112_init(struct mii_phy *phy)
3809e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo{
3819e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	/*
3829e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	 * Marvell 88E1112 PHY needs to have the SGMII MAC
3839e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	 * interace (page 2) properly configured to
3849e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	 * communicate with the 460EX/GT GPCS interface.
3859e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	 */
3869e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
3879e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	u16 reg_short;
3889e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
3899e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	pr_debug("%s: Marvell 88E1112 Ethernet\n", __func__);
3909e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
3919e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	/* Set access to Page 2 */
3929e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	phy_write(phy, 0x16, 0x0002);
3939e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
3949e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	phy_write(phy, 0x00, 0x0040); /* 1Gbps */
3959e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	reg_short = (u16)(phy_read(phy, 0x1a));
3969e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	reg_short |= 0x8000; /* bypass Auto-Negotiation */
3979e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	phy_write(phy, 0x1a, reg_short);
3989e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	emac_mii_reset_phy(phy); /* reset MAC interface */
3999e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
4009e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	/* Reset access to Page 0 */
4019e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	phy_write(phy, 0x16, 0x0000);
4029e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
4039e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	return  0;
4049e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo}
4059e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
4068df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roesestatic int et1011c_init(struct mii_phy *phy)
4078df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese{
4088df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	u16 reg_short;
4098df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese
4108df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	reg_short = (u16)(phy_read(phy, 0x16));
4118df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	reg_short &= ~(0x7);
4128df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	reg_short |= 0x6;	/* RGMII Trace Delay*/
4138df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	phy_write(phy, 0x16, reg_short);
4148df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese
4158df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	reg_short = (u16)(phy_read(phy, 0x17));
4168df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	reg_short &= ~(0x40);
4178df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	phy_write(phy, 0x17, reg_short);
4188df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese
4198df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	phy_write(phy, 0x1c, 0x74f0);
4208df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	return 0;
4218df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese}
4228df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese
4238df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roesestatic struct mii_phy_ops et1011c_phy_ops = {
4248df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	.init		= et1011c_init,
4258df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	.setup_aneg	= genmii_setup_aneg,
4268df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	.setup_forced	= genmii_setup_forced,
4278df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	.poll_link	= genmii_poll_link,
4288df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	.read_link	= genmii_read_link
4298df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese};
4308df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese
4318df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roesestatic struct mii_phy_def et1011c_phy_def = {
4328df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	.phy_id		= 0x0282f000,
4338df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	.phy_id_mask	= 0x0fffff00,
4348df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	.name		= "ET1011C Gigabit Ethernet",
4358df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	.ops		= &et1011c_phy_ops
4368df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese};
4378df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese
4388df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese
4398df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese
4408df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese
4418df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese
442f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roesestatic struct mii_phy_ops m88e1111_phy_ops = {
443f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.init		= m88e1111_init,
444f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.setup_aneg	= genmii_setup_aneg,
445f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.setup_forced	= genmii_setup_forced,
446f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.poll_link	= genmii_poll_link,
447f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.read_link	= genmii_read_link
448f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese};
449f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese
450f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roesestatic struct mii_phy_def m88e1111_phy_def = {
451f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese
452f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.phy_id		= 0x01410CC0,
453f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.phy_id_mask	= 0x0ffffff0,
454f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.name		= "Marvell 88E1111 Ethernet",
455f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	.ops		= &m88e1111_phy_ops,
456f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese};
457f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese
4589e3cb29497561c846d0e7efc445731764d93c749Victor Gallardostatic struct mii_phy_ops m88e1112_phy_ops = {
4599e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	.init		= m88e1112_init,
4609e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	.setup_aneg	= genmii_setup_aneg,
4619e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	.setup_forced	= genmii_setup_forced,
4629e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	.poll_link	= genmii_poll_link,
4639e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	.read_link	= genmii_read_link
4649e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo};
4659e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
4669e3cb29497561c846d0e7efc445731764d93c749Victor Gallardostatic struct mii_phy_def m88e1112_phy_def = {
4679e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	.phy_id		= 0x01410C90,
4689e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	.phy_id_mask	= 0x0ffffff0,
4699e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	.name		= "Marvell 88E1112 Ethernet",
4709e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	.ops		= &m88e1112_phy_ops,
4719e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo};
4729e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo
4731d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibsonstatic struct mii_phy_def *mii_phy_table[] = {
4748df4538e21f7313a29fa6c5af78c08a135d44738Stefan Roese	&et1011c_phy_def,
4751d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	&cis8201_phy_def,
476f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	&bcm5248_phy_def,
477f1f304f2e8fbc6ca80d5ef90132bd0772048f0efStefan Roese	&m88e1111_phy_def,
4789e3cb29497561c846d0e7efc445731764d93c749Victor Gallardo	&m88e1112_phy_def,
4791d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	&genmii_phy_def,
4801d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	NULL
4811d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson};
4821d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
4831d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibsonint emac_mii_phy_probe(struct mii_phy *phy, int address)
4841d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson{
4851d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	struct mii_phy_def *def;
4861d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	int i;
4871d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	u32 id;
4881d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
4891d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->autoneg = AUTONEG_DISABLE;
4901d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->advertising = 0;
4911d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->address = address;
4921d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->speed = SPEED_10;
4931d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->duplex = DUPLEX_HALF;
4941d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->pause = phy->asym_pause = 0;
4951d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
4961d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* Take PHY out of isolate mode and reset it. */
4971d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (emac_mii_reset_phy(phy))
4981d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		return -ENODEV;
4991d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
5001d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* Read ID and find matching entry */
5011d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	id = (phy_read(phy, MII_PHYSID1) << 16) | phy_read(phy, MII_PHYSID2);
5021d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	for (i = 0; (def = mii_phy_table[i]) != NULL; i++)
5031d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if ((id & def->phy_id_mask) == def->phy_id)
5041d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			break;
5051d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* Should never be NULL (we have a generic entry), but... */
5061d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (!def)
5071d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		return -ENODEV;
5081d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
5091d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->def = def;
5101d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
5111d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* Determine PHY features if needed */
5121d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->features = def->features;
5131d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	if (!phy->features) {
5141d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		u16 bmsr = phy_read(phy, MII_BMSR);
5151d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (bmsr & BMSR_ANEGCAPABLE)
5161d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->features |= SUPPORTED_Autoneg;
5171d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (bmsr & BMSR_10HALF)
5181d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->features |= SUPPORTED_10baseT_Half;
5191d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (bmsr & BMSR_10FULL)
5201d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->features |= SUPPORTED_10baseT_Full;
5211d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (bmsr & BMSR_100HALF)
5221d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->features |= SUPPORTED_100baseT_Half;
5231d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (bmsr & BMSR_100FULL)
5241d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			phy->features |= SUPPORTED_100baseT_Full;
5251d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		if (bmsr & BMSR_ESTATEN) {
5261d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			u16 esr = phy_read(phy, MII_ESTATUS);
5271d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			if (esr & ESTATUS_1000_TFULL)
5281d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson				phy->features |= SUPPORTED_1000baseT_Full;
5291d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson			if (esr & ESTATUS_1000_THALF)
5301d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson				phy->features |= SUPPORTED_1000baseT_Half;
5311d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		}
5321d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson		phy->features |= SUPPORTED_MII;
5331d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	}
5341d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
5351d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	/* Setup default advertising */
5361d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	phy->advertising = phy->features;
5371d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
5381d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson	return 0;
5391d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson}
5401d3bb996481e116f5f2b127cbd29b83365d2cf62David Gibson
5411d3bb996481e116f5f2b127cbd29b83365d2cf62David GibsonMODULE_LICENSE("GPL");
542