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