19082eeacSAndy Fleming /* 29082eeacSAndy Fleming * Marvell PHY drivers 39082eeacSAndy Fleming * 41a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 59082eeacSAndy Fleming * 69082eeacSAndy Fleming * Copyright 2010-2011 Freescale Semiconductor, Inc. 79082eeacSAndy Fleming * author Andy Fleming 89082eeacSAndy Fleming */ 99082eeacSAndy Fleming #include <config.h> 109082eeacSAndy Fleming #include <common.h> 11fbfa1abaSSimon Glass #include <errno.h> 129082eeacSAndy Fleming #include <phy.h> 139082eeacSAndy Fleming 149082eeacSAndy Fleming #define PHY_AUTONEGOTIATE_TIMEOUT 5000 159082eeacSAndy Fleming 169082eeacSAndy Fleming /* 88E1011 PHY Status Register */ 179082eeacSAndy Fleming #define MIIM_88E1xxx_PHY_STATUS 0x11 189082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_SPEED 0xc000 199082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_GBIT 0x8000 209082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_100 0x4000 219082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_DUPLEX 0x2000 229082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_SPDDONE 0x0800 239082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_LINK 0x0400 249082eeacSAndy Fleming 259082eeacSAndy Fleming #define MIIM_88E1xxx_PHY_SCR 0x10 269082eeacSAndy Fleming #define MIIM_88E1xxx_PHY_MDI_X_AUTO 0x0060 279082eeacSAndy Fleming 289082eeacSAndy Fleming /* 88E1111 PHY LED Control Register */ 299082eeacSAndy Fleming #define MIIM_88E1111_PHY_LED_CONTROL 24 309082eeacSAndy Fleming #define MIIM_88E1111_PHY_LED_DIRECT 0x4100 319082eeacSAndy Fleming #define MIIM_88E1111_PHY_LED_COMBINE 0x411C 329082eeacSAndy Fleming 33fa12a08eSZang Roy-R61911 /* 88E1111 Extended PHY Specific Control Register */ 34fa12a08eSZang Roy-R61911 #define MIIM_88E1111_PHY_EXT_CR 0x14 35fa12a08eSZang Roy-R61911 #define MIIM_88E1111_RX_DELAY 0x80 36fa12a08eSZang Roy-R61911 #define MIIM_88E1111_TX_DELAY 0x2 37fa12a08eSZang Roy-R61911 38fa12a08eSZang Roy-R61911 /* 88E1111 Extended PHY Specific Status Register */ 39fa12a08eSZang Roy-R61911 #define MIIM_88E1111_PHY_EXT_SR 0x1b 40fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_MASK 0xf 41fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_COPPER_RGMII 0xb 42fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_FIBER_RGMII 0x3 43fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK 0x4 44fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_COPPER_RTBI 0x9 45fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO 0x8000 46fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_FIBER_COPPER_RES 0x2000 47fa12a08eSZang Roy-R61911 48fa12a08eSZang Roy-R61911 #define MIIM_88E1111_COPPER 0 49fa12a08eSZang Roy-R61911 #define MIIM_88E1111_FIBER 1 50fa12a08eSZang Roy-R61911 519082eeacSAndy Fleming /* 88E1118 PHY defines */ 529082eeacSAndy Fleming #define MIIM_88E1118_PHY_PAGE 22 539082eeacSAndy Fleming #define MIIM_88E1118_PHY_LED_PAGE 3 549082eeacSAndy Fleming 559082eeacSAndy Fleming /* 88E1121 PHY LED Control Register */ 569082eeacSAndy Fleming #define MIIM_88E1121_PHY_LED_CTRL 16 579082eeacSAndy Fleming #define MIIM_88E1121_PHY_LED_PAGE 3 589082eeacSAndy Fleming #define MIIM_88E1121_PHY_LED_DEF 0x0030 599082eeacSAndy Fleming 609082eeacSAndy Fleming /* 88E1121 PHY IRQ Enable/Status Register */ 619082eeacSAndy Fleming #define MIIM_88E1121_PHY_IRQ_EN 18 629082eeacSAndy Fleming #define MIIM_88E1121_PHY_IRQ_STATUS 19 639082eeacSAndy Fleming 649082eeacSAndy Fleming #define MIIM_88E1121_PHY_PAGE 22 659082eeacSAndy Fleming 669082eeacSAndy Fleming /* 88E1145 Extended PHY Specific Control Register */ 679082eeacSAndy Fleming #define MIIM_88E1145_PHY_EXT_CR 20 689082eeacSAndy Fleming #define MIIM_M88E1145_RGMII_RX_DELAY 0x0080 699082eeacSAndy Fleming #define MIIM_M88E1145_RGMII_TX_DELAY 0x0002 709082eeacSAndy Fleming 719082eeacSAndy Fleming #define MIIM_88E1145_PHY_LED_CONTROL 24 729082eeacSAndy Fleming #define MIIM_88E1145_PHY_LED_DIRECT 0x4100 739082eeacSAndy Fleming 749082eeacSAndy Fleming #define MIIM_88E1145_PHY_PAGE 29 759082eeacSAndy Fleming #define MIIM_88E1145_PHY_CAL_OV 30 769082eeacSAndy Fleming 779082eeacSAndy Fleming #define MIIM_88E1149_PHY_PAGE 29 789082eeacSAndy Fleming 79aeceec0dSSebastian Hesselbarth /* 88E1310 PHY defines */ 80aeceec0dSSebastian Hesselbarth #define MIIM_88E1310_PHY_LED_CTRL 16 81aeceec0dSSebastian Hesselbarth #define MIIM_88E1310_PHY_IRQ_EN 18 82aeceec0dSSebastian Hesselbarth #define MIIM_88E1310_PHY_RGMII_CTRL 21 83aeceec0dSSebastian Hesselbarth #define MIIM_88E1310_PHY_PAGE 22 84aeceec0dSSebastian Hesselbarth 859082eeacSAndy Fleming /* Marvell 88E1011S */ 869082eeacSAndy Fleming static int m88e1011s_config(struct phy_device *phydev) 879082eeacSAndy Fleming { 889082eeacSAndy Fleming /* Reset and configure the PHY */ 899082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 909082eeacSAndy Fleming 919082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f); 929082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c); 939082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5); 949082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0); 959082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100); 969082eeacSAndy Fleming 979082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 989082eeacSAndy Fleming 999082eeacSAndy Fleming genphy_config_aneg(phydev); 1009082eeacSAndy Fleming 1019082eeacSAndy Fleming return 0; 1029082eeacSAndy Fleming } 1039082eeacSAndy Fleming 1049082eeacSAndy Fleming /* Parse the 88E1011's status register for speed and duplex 1059082eeacSAndy Fleming * information 1069082eeacSAndy Fleming */ 107ef5e821bSMichal Simek static int m88e1xxx_parse_status(struct phy_device *phydev) 1089082eeacSAndy Fleming { 1099082eeacSAndy Fleming unsigned int speed; 1109082eeacSAndy Fleming unsigned int mii_reg; 1119082eeacSAndy Fleming 1129082eeacSAndy Fleming mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_STATUS); 1139082eeacSAndy Fleming 1149082eeacSAndy Fleming if ((mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) && 1159082eeacSAndy Fleming !(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) { 1169082eeacSAndy Fleming int i = 0; 1179082eeacSAndy Fleming 1189082eeacSAndy Fleming puts("Waiting for PHY realtime link"); 1199082eeacSAndy Fleming while (!(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) { 1209082eeacSAndy Fleming /* Timeout reached ? */ 1219082eeacSAndy Fleming if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 1229082eeacSAndy Fleming puts(" TIMEOUT !\n"); 1239082eeacSAndy Fleming phydev->link = 0; 124ef5e821bSMichal Simek return -ETIMEDOUT; 1259082eeacSAndy Fleming } 1269082eeacSAndy Fleming 1279082eeacSAndy Fleming if ((i++ % 1000) == 0) 1289082eeacSAndy Fleming putc('.'); 1299082eeacSAndy Fleming udelay(1000); 1309082eeacSAndy Fleming mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 1319082eeacSAndy Fleming MIIM_88E1xxx_PHY_STATUS); 1329082eeacSAndy Fleming } 1339082eeacSAndy Fleming puts(" done\n"); 1349082eeacSAndy Fleming udelay(500000); /* another 500 ms (results in faster booting) */ 1359082eeacSAndy Fleming } else { 1369082eeacSAndy Fleming if (mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) 1379082eeacSAndy Fleming phydev->link = 1; 1389082eeacSAndy Fleming else 1399082eeacSAndy Fleming phydev->link = 0; 1409082eeacSAndy Fleming } 1419082eeacSAndy Fleming 1429082eeacSAndy Fleming if (mii_reg & MIIM_88E1xxx_PHYSTAT_DUPLEX) 1439082eeacSAndy Fleming phydev->duplex = DUPLEX_FULL; 1449082eeacSAndy Fleming else 1459082eeacSAndy Fleming phydev->duplex = DUPLEX_HALF; 1469082eeacSAndy Fleming 1479082eeacSAndy Fleming speed = mii_reg & MIIM_88E1xxx_PHYSTAT_SPEED; 1489082eeacSAndy Fleming 1499082eeacSAndy Fleming switch (speed) { 1509082eeacSAndy Fleming case MIIM_88E1xxx_PHYSTAT_GBIT: 1519082eeacSAndy Fleming phydev->speed = SPEED_1000; 1529082eeacSAndy Fleming break; 1539082eeacSAndy Fleming case MIIM_88E1xxx_PHYSTAT_100: 1549082eeacSAndy Fleming phydev->speed = SPEED_100; 1559082eeacSAndy Fleming break; 1569082eeacSAndy Fleming default: 1579082eeacSAndy Fleming phydev->speed = SPEED_10; 1589082eeacSAndy Fleming break; 1599082eeacSAndy Fleming } 1609082eeacSAndy Fleming 1619082eeacSAndy Fleming return 0; 1629082eeacSAndy Fleming } 1639082eeacSAndy Fleming 1649082eeacSAndy Fleming static int m88e1011s_startup(struct phy_device *phydev) 1659082eeacSAndy Fleming { 166b733c278SMichal Simek int ret; 1679082eeacSAndy Fleming 168b733c278SMichal Simek ret = genphy_update_link(phydev); 169b733c278SMichal Simek if (ret) 170b733c278SMichal Simek return ret; 171b733c278SMichal Simek 172b733c278SMichal Simek return m88e1xxx_parse_status(phydev); 1739082eeacSAndy Fleming } 1749082eeacSAndy Fleming 1759082eeacSAndy Fleming /* Marvell 88E1111S */ 1769082eeacSAndy Fleming static int m88e1111s_config(struct phy_device *phydev) 1779082eeacSAndy Fleming { 1789082eeacSAndy Fleming int reg; 1799082eeacSAndy Fleming 180*24d98cb4SPhil Edworthy if (phy_interface_is_rgmii(phydev)) { 181fa12a08eSZang Roy-R61911 reg = phy_read(phydev, 182fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); 183fa12a08eSZang Roy-R61911 if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 184fa12a08eSZang Roy-R61911 (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) { 185fa12a08eSZang Roy-R61911 reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY); 186fa12a08eSZang Roy-R61911 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 187fa12a08eSZang Roy-R61911 reg &= ~MIIM_88E1111_TX_DELAY; 188fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_RX_DELAY; 189fa12a08eSZang Roy-R61911 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 190fa12a08eSZang Roy-R61911 reg &= ~MIIM_88E1111_RX_DELAY; 191fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_TX_DELAY; 1929082eeacSAndy Fleming } 1939082eeacSAndy Fleming 194fa12a08eSZang Roy-R61911 phy_write(phydev, 195fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); 196fa12a08eSZang Roy-R61911 197fa12a08eSZang Roy-R61911 reg = phy_read(phydev, 198fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); 199fa12a08eSZang Roy-R61911 200fa12a08eSZang Roy-R61911 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); 201fa12a08eSZang Roy-R61911 202fa12a08eSZang Roy-R61911 if (reg & MIIM_88E1111_HWCFG_FIBER_COPPER_RES) 203fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_MODE_FIBER_RGMII; 204fa12a08eSZang Roy-R61911 else 205fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RGMII; 206fa12a08eSZang Roy-R61911 207fa12a08eSZang Roy-R61911 phy_write(phydev, 208fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg); 209fa12a08eSZang Roy-R61911 } 210fa12a08eSZang Roy-R61911 211fa12a08eSZang Roy-R61911 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { 212fa12a08eSZang Roy-R61911 reg = phy_read(phydev, 213fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); 214fa12a08eSZang Roy-R61911 215fa12a08eSZang Roy-R61911 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); 216fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK; 217fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; 218fa12a08eSZang Roy-R61911 219fa12a08eSZang Roy-R61911 phy_write(phydev, MDIO_DEVAD_NONE, 220fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR, reg); 221fa12a08eSZang Roy-R61911 } 222fa12a08eSZang Roy-R61911 223fa12a08eSZang Roy-R61911 if (phydev->interface == PHY_INTERFACE_MODE_RTBI) { 224fa12a08eSZang Roy-R61911 reg = phy_read(phydev, 225fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); 226fa12a08eSZang Roy-R61911 reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY); 227fa12a08eSZang Roy-R61911 phy_write(phydev, 228fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); 229fa12a08eSZang Roy-R61911 230fa12a08eSZang Roy-R61911 reg = phy_read(phydev, MDIO_DEVAD_NONE, 231fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR); 232fa12a08eSZang Roy-R61911 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | 233fa12a08eSZang Roy-R61911 MIIM_88E1111_HWCFG_FIBER_COPPER_RES); 234fa12a08eSZang Roy-R61911 reg |= 0x7 | MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; 235fa12a08eSZang Roy-R61911 phy_write(phydev, MDIO_DEVAD_NONE, 236fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR, reg); 237fa12a08eSZang Roy-R61911 238fa12a08eSZang Roy-R61911 /* soft reset */ 2393089c47dSStefan Roese phy_reset(phydev); 240fa12a08eSZang Roy-R61911 241fa12a08eSZang Roy-R61911 reg = phy_read(phydev, MDIO_DEVAD_NONE, 242fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR); 243fa12a08eSZang Roy-R61911 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | 244fa12a08eSZang Roy-R61911 MIIM_88E1111_HWCFG_FIBER_COPPER_RES); 245fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RTBI | 246fa12a08eSZang Roy-R61911 MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; 247fa12a08eSZang Roy-R61911 phy_write(phydev, MDIO_DEVAD_NONE, 248fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR, reg); 249fa12a08eSZang Roy-R61911 } 250fa12a08eSZang Roy-R61911 251fa12a08eSZang Roy-R61911 /* soft reset */ 2523089c47dSStefan Roese phy_reset(phydev); 2539082eeacSAndy Fleming 2549082eeacSAndy Fleming genphy_config_aneg(phydev); 255a8c3eca4SStefan Roese genphy_restart_aneg(phydev); 2569082eeacSAndy Fleming 2579082eeacSAndy Fleming return 0; 2589082eeacSAndy Fleming } 2599082eeacSAndy Fleming 26035fa0ddaSHao Zhang /** 26135fa0ddaSHao Zhang * m88e1518_phy_writebits - write bits to a register 26235fa0ddaSHao Zhang */ 26335fa0ddaSHao Zhang void m88e1518_phy_writebits(struct phy_device *phydev, 26435fa0ddaSHao Zhang u8 reg_num, u16 offset, u16 len, u16 data) 26535fa0ddaSHao Zhang { 26635fa0ddaSHao Zhang u16 reg, mask; 26735fa0ddaSHao Zhang 26835fa0ddaSHao Zhang if ((len + offset) >= 16) 26935fa0ddaSHao Zhang mask = 0 - (1 << offset); 27035fa0ddaSHao Zhang else 27135fa0ddaSHao Zhang mask = (1 << (len + offset)) - (1 << offset); 27235fa0ddaSHao Zhang 27335fa0ddaSHao Zhang reg = phy_read(phydev, MDIO_DEVAD_NONE, reg_num); 27435fa0ddaSHao Zhang 27535fa0ddaSHao Zhang reg &= ~mask; 27635fa0ddaSHao Zhang reg |= data << offset; 27735fa0ddaSHao Zhang 27835fa0ddaSHao Zhang phy_write(phydev, MDIO_DEVAD_NONE, reg_num, reg); 27935fa0ddaSHao Zhang } 28035fa0ddaSHao Zhang 28135fa0ddaSHao Zhang static int m88e1518_config(struct phy_device *phydev) 28235fa0ddaSHao Zhang { 28335fa0ddaSHao Zhang /* 28435fa0ddaSHao Zhang * As per Marvell Release Notes - Alaska 88E1510/88E1518/88E1512 28535fa0ddaSHao Zhang * /88E1514 Rev A0, Errata Section 3.1 28635fa0ddaSHao Zhang */ 28790a94ef6SClemens Gruber 28890a94ef6SClemens Gruber /* EEE initialization */ 28990a94ef6SClemens Gruber phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x00ff); 29035fa0ddaSHao Zhang phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x214B); 29135fa0ddaSHao Zhang phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2144); 29235fa0ddaSHao Zhang phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x0C28); 29335fa0ddaSHao Zhang phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2146); 29435fa0ddaSHao Zhang phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xB233); 29535fa0ddaSHao Zhang phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x214D); 29635fa0ddaSHao Zhang phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xCC0C); 29735fa0ddaSHao Zhang phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2159); 29890a94ef6SClemens Gruber phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000); 29990a94ef6SClemens Gruber 30090a94ef6SClemens Gruber /* SGMII-to-Copper mode initialization */ 30190a94ef6SClemens Gruber if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { 30290a94ef6SClemens Gruber /* Select page 18 */ 30390a94ef6SClemens Gruber phy_write(phydev, MDIO_DEVAD_NONE, 22, 18); 30490a94ef6SClemens Gruber 30590a94ef6SClemens Gruber /* In reg 20, write MODE[2:0] = 0x1 (SGMII to Copper) */ 30635fa0ddaSHao Zhang m88e1518_phy_writebits(phydev, 20, 0, 3, 1); 30735fa0ddaSHao Zhang 30890a94ef6SClemens Gruber /* PHY reset is necessary after changing MODE[2:0] */ 30935fa0ddaSHao Zhang m88e1518_phy_writebits(phydev, 20, 15, 1, 1); 31090a94ef6SClemens Gruber 31190a94ef6SClemens Gruber /* Reset page selection */ 31290a94ef6SClemens Gruber phy_write(phydev, MDIO_DEVAD_NONE, 22, 0); 31390a94ef6SClemens Gruber 31435fa0ddaSHao Zhang udelay(100); 31535fa0ddaSHao Zhang } 31635fa0ddaSHao Zhang 31735fa0ddaSHao Zhang return m88e1111s_config(phydev); 31835fa0ddaSHao Zhang } 31935fa0ddaSHao Zhang 3208396d0abSClemens Gruber /* Marvell 88E1510 */ 3218396d0abSClemens Gruber static int m88e1510_config(struct phy_device *phydev) 3228396d0abSClemens Gruber { 3238396d0abSClemens Gruber /* Select page 3 */ 3248396d0abSClemens Gruber phy_write(phydev, MDIO_DEVAD_NONE, 22, 3); 3258396d0abSClemens Gruber 3268396d0abSClemens Gruber /* Enable INTn output on LED[2] */ 3278396d0abSClemens Gruber m88e1518_phy_writebits(phydev, 18, 7, 1, 1); 3288396d0abSClemens Gruber 3298396d0abSClemens Gruber /* Configure LEDs */ 3308396d0abSClemens Gruber m88e1518_phy_writebits(phydev, 16, 0, 4, 3); /* LED[0]:0011 (ACT) */ 3318396d0abSClemens Gruber m88e1518_phy_writebits(phydev, 16, 4, 4, 6); /* LED[1]:0110 (LINK) */ 3328396d0abSClemens Gruber 3338396d0abSClemens Gruber /* Reset page selection */ 3348396d0abSClemens Gruber phy_write(phydev, MDIO_DEVAD_NONE, 22, 0); 3358396d0abSClemens Gruber 3368396d0abSClemens Gruber return m88e1518_config(phydev); 3378396d0abSClemens Gruber } 3388396d0abSClemens Gruber 3399082eeacSAndy Fleming /* Marvell 88E1118 */ 3409082eeacSAndy Fleming static int m88e1118_config(struct phy_device *phydev) 3419082eeacSAndy Fleming { 3429082eeacSAndy Fleming /* Change Page Number */ 3439082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0002); 3449082eeacSAndy Fleming /* Delay RGMII TX and RX */ 3459082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x1070); 3469082eeacSAndy Fleming /* Change Page Number */ 3479082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0003); 3489082eeacSAndy Fleming /* Adjust LED control */ 3499082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x021e); 3509082eeacSAndy Fleming /* Change Page Number */ 3519082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); 3529082eeacSAndy Fleming 3531b008fdbSMichal Simek return genphy_config_aneg(phydev); 3549082eeacSAndy Fleming } 3559082eeacSAndy Fleming 3569082eeacSAndy Fleming static int m88e1118_startup(struct phy_device *phydev) 3579082eeacSAndy Fleming { 358b733c278SMichal Simek int ret; 359b733c278SMichal Simek 3609082eeacSAndy Fleming /* Change Page Number */ 3619082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); 3629082eeacSAndy Fleming 363b733c278SMichal Simek ret = genphy_update_link(phydev); 364b733c278SMichal Simek if (ret) 365b733c278SMichal Simek return ret; 3669082eeacSAndy Fleming 367b733c278SMichal Simek return m88e1xxx_parse_status(phydev); 3689082eeacSAndy Fleming } 3699082eeacSAndy Fleming 3709082eeacSAndy Fleming /* Marvell 88E1121R */ 3719082eeacSAndy Fleming static int m88e1121_config(struct phy_device *phydev) 3729082eeacSAndy Fleming { 3739082eeacSAndy Fleming int pg; 3749082eeacSAndy Fleming 3759082eeacSAndy Fleming /* Configure the PHY */ 3769082eeacSAndy Fleming genphy_config_aneg(phydev); 3779082eeacSAndy Fleming 3789082eeacSAndy Fleming /* Switch the page to access the led register */ 3799082eeacSAndy Fleming pg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE); 3809082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, 3819082eeacSAndy Fleming MIIM_88E1121_PHY_LED_PAGE); 3829082eeacSAndy Fleming /* Configure leds */ 3839082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_LED_CTRL, 3849082eeacSAndy Fleming MIIM_88E1121_PHY_LED_DEF); 3859082eeacSAndy Fleming /* Restore the page pointer */ 3869082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, pg); 3879082eeacSAndy Fleming 3889082eeacSAndy Fleming /* Disable IRQs and de-assert interrupt */ 3899082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_EN, 0); 3909082eeacSAndy Fleming phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_STATUS); 3919082eeacSAndy Fleming 3929082eeacSAndy Fleming return 0; 3939082eeacSAndy Fleming } 3949082eeacSAndy Fleming 3959082eeacSAndy Fleming /* Marvell 88E1145 */ 3969082eeacSAndy Fleming static int m88e1145_config(struct phy_device *phydev) 3979082eeacSAndy Fleming { 3989082eeacSAndy Fleming int reg; 3999082eeacSAndy Fleming 4009082eeacSAndy Fleming /* Errata E0, E1 */ 4019082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x001b); 4029082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0x418f); 4039082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x0016); 4049082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0xa2da); 4059082eeacSAndy Fleming 4069082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_SCR, 4079082eeacSAndy Fleming MIIM_88E1xxx_PHY_MDI_X_AUTO); 4089082eeacSAndy Fleming 4099082eeacSAndy Fleming reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR); 4109082eeacSAndy Fleming if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 4119082eeacSAndy Fleming reg |= MIIM_M88E1145_RGMII_RX_DELAY | 4129082eeacSAndy Fleming MIIM_M88E1145_RGMII_TX_DELAY; 4139082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg); 4149082eeacSAndy Fleming 4159082eeacSAndy Fleming genphy_config_aneg(phydev); 4169082eeacSAndy Fleming 4179082eeacSAndy Fleming phy_reset(phydev); 4189082eeacSAndy Fleming 4199082eeacSAndy Fleming return 0; 4209082eeacSAndy Fleming } 4219082eeacSAndy Fleming 4229082eeacSAndy Fleming static int m88e1145_startup(struct phy_device *phydev) 4239082eeacSAndy Fleming { 424b733c278SMichal Simek int ret; 425b733c278SMichal Simek 426b733c278SMichal Simek ret = genphy_update_link(phydev); 427b733c278SMichal Simek if (ret) 428b733c278SMichal Simek return ret; 429b733c278SMichal Simek 4309082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_LED_CONTROL, 4319082eeacSAndy Fleming MIIM_88E1145_PHY_LED_DIRECT); 432b733c278SMichal Simek return m88e1xxx_parse_status(phydev); 4339082eeacSAndy Fleming } 4349082eeacSAndy Fleming 4359082eeacSAndy Fleming /* Marvell 88E1149S */ 4369082eeacSAndy Fleming static int m88e1149_config(struct phy_device *phydev) 4379082eeacSAndy Fleming { 4389082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x1f); 4399082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c); 4409082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x5); 4419082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0); 4429082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100); 4439082eeacSAndy Fleming 4449082eeacSAndy Fleming genphy_config_aneg(phydev); 4459082eeacSAndy Fleming 4469082eeacSAndy Fleming phy_reset(phydev); 4479082eeacSAndy Fleming 4489082eeacSAndy Fleming return 0; 4499082eeacSAndy Fleming } 4509082eeacSAndy Fleming 451aeceec0dSSebastian Hesselbarth /* Marvell 88E1310 */ 452aeceec0dSSebastian Hesselbarth static int m88e1310_config(struct phy_device *phydev) 453aeceec0dSSebastian Hesselbarth { 454aeceec0dSSebastian Hesselbarth u16 reg; 455aeceec0dSSebastian Hesselbarth 456aeceec0dSSebastian Hesselbarth /* LED link and activity */ 457aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003); 458aeceec0dSSebastian Hesselbarth reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL); 459aeceec0dSSebastian Hesselbarth reg = (reg & ~0xf) | 0x1; 460aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL, reg); 461aeceec0dSSebastian Hesselbarth 462aeceec0dSSebastian Hesselbarth /* Set LED2/INT to INT mode, low active */ 463aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003); 464aeceec0dSSebastian Hesselbarth reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN); 465aeceec0dSSebastian Hesselbarth reg = (reg & 0x77ff) | 0x0880; 466aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN, reg); 467aeceec0dSSebastian Hesselbarth 468aeceec0dSSebastian Hesselbarth /* Set RGMII delay */ 469aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0002); 470aeceec0dSSebastian Hesselbarth reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL); 471aeceec0dSSebastian Hesselbarth reg |= 0x0030; 472aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL, reg); 473aeceec0dSSebastian Hesselbarth 474aeceec0dSSebastian Hesselbarth /* Ensure to return to page 0 */ 475aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000); 476aeceec0dSSebastian Hesselbarth 47708e64cecSNathan Rossi return genphy_config_aneg(phydev); 478aeceec0dSSebastian Hesselbarth } 4799082eeacSAndy Fleming 480c52d428dSDirk Eibach static int m88e1680_config(struct phy_device *phydev) 481c52d428dSDirk Eibach { 482c52d428dSDirk Eibach /* 483c52d428dSDirk Eibach * As per Marvell Release Notes - Alaska V 88E1680 Rev A2 484c52d428dSDirk Eibach * Errata Section 4.1 485c52d428dSDirk Eibach */ 486c52d428dSDirk Eibach u16 reg; 487c52d428dSDirk Eibach int res; 488c52d428dSDirk Eibach 489c52d428dSDirk Eibach /* Matrix LED mode (not neede if single LED mode is used */ 490c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0004); 491c52d428dSDirk Eibach reg = phy_read(phydev, MDIO_DEVAD_NONE, 27); 492c52d428dSDirk Eibach reg |= (1 << 5); 493c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, 27, reg); 494c52d428dSDirk Eibach 495c52d428dSDirk Eibach /* QSGMII TX amplitude change */ 496c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00fd); 497c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, 8, 0x0b53); 498c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, 7, 0x200d); 499c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); 500c52d428dSDirk Eibach 501c52d428dSDirk Eibach /* EEE initialization */ 502c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00ff); 503c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xb030); 504c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x215c); 505c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x00fc); 506c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, 24, 0x888c); 507c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, 25, 0x888c); 508c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); 509c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, 0, 0x9140); 510c52d428dSDirk Eibach 511c52d428dSDirk Eibach res = genphy_config_aneg(phydev); 512c52d428dSDirk Eibach if (res < 0) 513c52d428dSDirk Eibach return res; 514c52d428dSDirk Eibach 515c52d428dSDirk Eibach /* soft reset */ 516c52d428dSDirk Eibach reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 517c52d428dSDirk Eibach reg |= BMCR_RESET; 518c52d428dSDirk Eibach phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, reg); 519c52d428dSDirk Eibach 520c52d428dSDirk Eibach return 0; 521c52d428dSDirk Eibach } 522c52d428dSDirk Eibach 5239082eeacSAndy Fleming static struct phy_driver M88E1011S_driver = { 5249082eeacSAndy Fleming .name = "Marvell 88E1011S", 5259082eeacSAndy Fleming .uid = 0x1410c60, 5269082eeacSAndy Fleming .mask = 0xffffff0, 5279082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 5289082eeacSAndy Fleming .config = &m88e1011s_config, 5299082eeacSAndy Fleming .startup = &m88e1011s_startup, 5309082eeacSAndy Fleming .shutdown = &genphy_shutdown, 5319082eeacSAndy Fleming }; 5329082eeacSAndy Fleming 5339082eeacSAndy Fleming static struct phy_driver M88E1111S_driver = { 5349082eeacSAndy Fleming .name = "Marvell 88E1111S", 5359082eeacSAndy Fleming .uid = 0x1410cc0, 5369082eeacSAndy Fleming .mask = 0xffffff0, 5379082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 5389082eeacSAndy Fleming .config = &m88e1111s_config, 5399082eeacSAndy Fleming .startup = &m88e1011s_startup, 5409082eeacSAndy Fleming .shutdown = &genphy_shutdown, 5419082eeacSAndy Fleming }; 5429082eeacSAndy Fleming 5439082eeacSAndy Fleming static struct phy_driver M88E1118_driver = { 5449082eeacSAndy Fleming .name = "Marvell 88E1118", 5459082eeacSAndy Fleming .uid = 0x1410e10, 5469082eeacSAndy Fleming .mask = 0xffffff0, 5479082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 5489082eeacSAndy Fleming .config = &m88e1118_config, 5499082eeacSAndy Fleming .startup = &m88e1118_startup, 5509082eeacSAndy Fleming .shutdown = &genphy_shutdown, 5519082eeacSAndy Fleming }; 5529082eeacSAndy Fleming 553b4b81e83SMichal Simek static struct phy_driver M88E1118R_driver = { 554b4b81e83SMichal Simek .name = "Marvell 88E1118R", 555b4b81e83SMichal Simek .uid = 0x1410e40, 556b4b81e83SMichal Simek .mask = 0xffffff0, 557b4b81e83SMichal Simek .features = PHY_GBIT_FEATURES, 558b4b81e83SMichal Simek .config = &m88e1118_config, 559b4b81e83SMichal Simek .startup = &m88e1118_startup, 560b4b81e83SMichal Simek .shutdown = &genphy_shutdown, 561b4b81e83SMichal Simek }; 562b4b81e83SMichal Simek 5639082eeacSAndy Fleming static struct phy_driver M88E1121R_driver = { 5649082eeacSAndy Fleming .name = "Marvell 88E1121R", 5659082eeacSAndy Fleming .uid = 0x1410cb0, 5669082eeacSAndy Fleming .mask = 0xffffff0, 5679082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 5689082eeacSAndy Fleming .config = &m88e1121_config, 5699082eeacSAndy Fleming .startup = &genphy_startup, 5709082eeacSAndy Fleming .shutdown = &genphy_shutdown, 5719082eeacSAndy Fleming }; 5729082eeacSAndy Fleming 5739082eeacSAndy Fleming static struct phy_driver M88E1145_driver = { 5749082eeacSAndy Fleming .name = "Marvell 88E1145", 5759082eeacSAndy Fleming .uid = 0x1410cd0, 5769082eeacSAndy Fleming .mask = 0xffffff0, 5779082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 5789082eeacSAndy Fleming .config = &m88e1145_config, 5799082eeacSAndy Fleming .startup = &m88e1145_startup, 5809082eeacSAndy Fleming .shutdown = &genphy_shutdown, 5819082eeacSAndy Fleming }; 5829082eeacSAndy Fleming 5839082eeacSAndy Fleming static struct phy_driver M88E1149S_driver = { 5849082eeacSAndy Fleming .name = "Marvell 88E1149S", 5859082eeacSAndy Fleming .uid = 0x1410ca0, 5869082eeacSAndy Fleming .mask = 0xffffff0, 5879082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 5889082eeacSAndy Fleming .config = &m88e1149_config, 5899082eeacSAndy Fleming .startup = &m88e1011s_startup, 5909082eeacSAndy Fleming .shutdown = &genphy_shutdown, 5919082eeacSAndy Fleming }; 5929082eeacSAndy Fleming 5938396d0abSClemens Gruber static struct phy_driver M88E1510_driver = { 5948396d0abSClemens Gruber .name = "Marvell 88E1510", 5958396d0abSClemens Gruber .uid = 0x1410dd0, 59683cfbeb0SPhil Edworthy .mask = 0xfffffff, 5978396d0abSClemens Gruber .features = PHY_GBIT_FEATURES, 5988396d0abSClemens Gruber .config = &m88e1510_config, 5998396d0abSClemens Gruber .startup = &m88e1011s_startup, 6008396d0abSClemens Gruber .shutdown = &genphy_shutdown, 6018396d0abSClemens Gruber }; 6028396d0abSClemens Gruber 603998640b4SPhil Edworthy /* 604998640b4SPhil Edworthy * This supports: 605998640b4SPhil Edworthy * 88E1518, uid 0x1410dd1 606998640b4SPhil Edworthy * 88E1512, uid 0x1410dd4 607998640b4SPhil Edworthy */ 6081415107eSMichal Simek static struct phy_driver M88E1518_driver = { 6091415107eSMichal Simek .name = "Marvell 88E1518", 610998640b4SPhil Edworthy .uid = 0x1410dd0, 611998640b4SPhil Edworthy .mask = 0xffffffa, 6121415107eSMichal Simek .features = PHY_GBIT_FEATURES, 61335fa0ddaSHao Zhang .config = &m88e1518_config, 6141415107eSMichal Simek .startup = &m88e1011s_startup, 6151415107eSMichal Simek .shutdown = &genphy_shutdown, 6161415107eSMichal Simek }; 6171415107eSMichal Simek 618aeceec0dSSebastian Hesselbarth static struct phy_driver M88E1310_driver = { 619aeceec0dSSebastian Hesselbarth .name = "Marvell 88E1310", 620aeceec0dSSebastian Hesselbarth .uid = 0x01410e90, 621aeceec0dSSebastian Hesselbarth .mask = 0xffffff0, 622aeceec0dSSebastian Hesselbarth .features = PHY_GBIT_FEATURES, 623aeceec0dSSebastian Hesselbarth .config = &m88e1310_config, 624aeceec0dSSebastian Hesselbarth .startup = &m88e1011s_startup, 625aeceec0dSSebastian Hesselbarth .shutdown = &genphy_shutdown, 626aeceec0dSSebastian Hesselbarth }; 627aeceec0dSSebastian Hesselbarth 628c52d428dSDirk Eibach static struct phy_driver M88E1680_driver = { 629c52d428dSDirk Eibach .name = "Marvell 88E1680", 630c52d428dSDirk Eibach .uid = 0x1410ed0, 631c52d428dSDirk Eibach .mask = 0xffffff0, 632c52d428dSDirk Eibach .features = PHY_GBIT_FEATURES, 633c52d428dSDirk Eibach .config = &m88e1680_config, 634c52d428dSDirk Eibach .startup = &genphy_startup, 635c52d428dSDirk Eibach .shutdown = &genphy_shutdown, 636c52d428dSDirk Eibach }; 637c52d428dSDirk Eibach 6389082eeacSAndy Fleming int phy_marvell_init(void) 6399082eeacSAndy Fleming { 640aeceec0dSSebastian Hesselbarth phy_register(&M88E1310_driver); 6419082eeacSAndy Fleming phy_register(&M88E1149S_driver); 6429082eeacSAndy Fleming phy_register(&M88E1145_driver); 6439082eeacSAndy Fleming phy_register(&M88E1121R_driver); 6449082eeacSAndy Fleming phy_register(&M88E1118_driver); 645b4b81e83SMichal Simek phy_register(&M88E1118R_driver); 6469082eeacSAndy Fleming phy_register(&M88E1111S_driver); 6479082eeacSAndy Fleming phy_register(&M88E1011S_driver); 6488396d0abSClemens Gruber phy_register(&M88E1510_driver); 6491415107eSMichal Simek phy_register(&M88E1518_driver); 650c52d428dSDirk Eibach phy_register(&M88E1680_driver); 6519082eeacSAndy Fleming 6529082eeacSAndy Fleming return 0; 6539082eeacSAndy Fleming } 654