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> 119082eeacSAndy Fleming #include <phy.h> 129082eeacSAndy Fleming 139082eeacSAndy Fleming #define PHY_AUTONEGOTIATE_TIMEOUT 5000 149082eeacSAndy Fleming 159082eeacSAndy Fleming /* 88E1011 PHY Status Register */ 169082eeacSAndy Fleming #define MIIM_88E1xxx_PHY_STATUS 0x11 179082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_SPEED 0xc000 189082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_GBIT 0x8000 199082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_100 0x4000 209082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_DUPLEX 0x2000 219082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_SPDDONE 0x0800 229082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_LINK 0x0400 239082eeacSAndy Fleming 249082eeacSAndy Fleming #define MIIM_88E1xxx_PHY_SCR 0x10 259082eeacSAndy Fleming #define MIIM_88E1xxx_PHY_MDI_X_AUTO 0x0060 269082eeacSAndy Fleming 279082eeacSAndy Fleming /* 88E1111 PHY LED Control Register */ 289082eeacSAndy Fleming #define MIIM_88E1111_PHY_LED_CONTROL 24 299082eeacSAndy Fleming #define MIIM_88E1111_PHY_LED_DIRECT 0x4100 309082eeacSAndy Fleming #define MIIM_88E1111_PHY_LED_COMBINE 0x411C 319082eeacSAndy Fleming 32fa12a08eSZang Roy-R61911 /* 88E1111 Extended PHY Specific Control Register */ 33fa12a08eSZang Roy-R61911 #define MIIM_88E1111_PHY_EXT_CR 0x14 34fa12a08eSZang Roy-R61911 #define MIIM_88E1111_RX_DELAY 0x80 35fa12a08eSZang Roy-R61911 #define MIIM_88E1111_TX_DELAY 0x2 36fa12a08eSZang Roy-R61911 37fa12a08eSZang Roy-R61911 /* 88E1111 Extended PHY Specific Status Register */ 38fa12a08eSZang Roy-R61911 #define MIIM_88E1111_PHY_EXT_SR 0x1b 39fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_MASK 0xf 40fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_COPPER_RGMII 0xb 41fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_FIBER_RGMII 0x3 42fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK 0x4 43fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_COPPER_RTBI 0x9 44fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO 0x8000 45fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_FIBER_COPPER_RES 0x2000 46fa12a08eSZang Roy-R61911 47fa12a08eSZang Roy-R61911 #define MIIM_88E1111_COPPER 0 48fa12a08eSZang Roy-R61911 #define MIIM_88E1111_FIBER 1 49fa12a08eSZang Roy-R61911 509082eeacSAndy Fleming /* 88E1118 PHY defines */ 519082eeacSAndy Fleming #define MIIM_88E1118_PHY_PAGE 22 529082eeacSAndy Fleming #define MIIM_88E1118_PHY_LED_PAGE 3 539082eeacSAndy Fleming 549082eeacSAndy Fleming /* 88E1121 PHY LED Control Register */ 559082eeacSAndy Fleming #define MIIM_88E1121_PHY_LED_CTRL 16 569082eeacSAndy Fleming #define MIIM_88E1121_PHY_LED_PAGE 3 579082eeacSAndy Fleming #define MIIM_88E1121_PHY_LED_DEF 0x0030 589082eeacSAndy Fleming 599082eeacSAndy Fleming /* 88E1121 PHY IRQ Enable/Status Register */ 609082eeacSAndy Fleming #define MIIM_88E1121_PHY_IRQ_EN 18 619082eeacSAndy Fleming #define MIIM_88E1121_PHY_IRQ_STATUS 19 629082eeacSAndy Fleming 639082eeacSAndy Fleming #define MIIM_88E1121_PHY_PAGE 22 649082eeacSAndy Fleming 659082eeacSAndy Fleming /* 88E1145 Extended PHY Specific Control Register */ 669082eeacSAndy Fleming #define MIIM_88E1145_PHY_EXT_CR 20 679082eeacSAndy Fleming #define MIIM_M88E1145_RGMII_RX_DELAY 0x0080 689082eeacSAndy Fleming #define MIIM_M88E1145_RGMII_TX_DELAY 0x0002 699082eeacSAndy Fleming 709082eeacSAndy Fleming #define MIIM_88E1145_PHY_LED_CONTROL 24 719082eeacSAndy Fleming #define MIIM_88E1145_PHY_LED_DIRECT 0x4100 729082eeacSAndy Fleming 739082eeacSAndy Fleming #define MIIM_88E1145_PHY_PAGE 29 749082eeacSAndy Fleming #define MIIM_88E1145_PHY_CAL_OV 30 759082eeacSAndy Fleming 769082eeacSAndy Fleming #define MIIM_88E1149_PHY_PAGE 29 779082eeacSAndy Fleming 78aeceec0dSSebastian Hesselbarth /* 88E1310 PHY defines */ 79aeceec0dSSebastian Hesselbarth #define MIIM_88E1310_PHY_LED_CTRL 16 80aeceec0dSSebastian Hesselbarth #define MIIM_88E1310_PHY_IRQ_EN 18 81aeceec0dSSebastian Hesselbarth #define MIIM_88E1310_PHY_RGMII_CTRL 21 82aeceec0dSSebastian Hesselbarth #define MIIM_88E1310_PHY_PAGE 22 83aeceec0dSSebastian Hesselbarth 849082eeacSAndy Fleming /* Marvell 88E1011S */ 859082eeacSAndy Fleming static int m88e1011s_config(struct phy_device *phydev) 869082eeacSAndy Fleming { 879082eeacSAndy Fleming /* Reset and configure the PHY */ 889082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 899082eeacSAndy Fleming 909082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f); 919082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c); 929082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5); 939082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0); 949082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100); 959082eeacSAndy Fleming 969082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 979082eeacSAndy Fleming 989082eeacSAndy Fleming genphy_config_aneg(phydev); 999082eeacSAndy Fleming 1009082eeacSAndy Fleming return 0; 1019082eeacSAndy Fleming } 1029082eeacSAndy Fleming 1039082eeacSAndy Fleming /* Parse the 88E1011's status register for speed and duplex 1049082eeacSAndy Fleming * information 1059082eeacSAndy Fleming */ 1069082eeacSAndy Fleming static uint m88e1xxx_parse_status(struct phy_device *phydev) 1079082eeacSAndy Fleming { 1089082eeacSAndy Fleming unsigned int speed; 1099082eeacSAndy Fleming unsigned int mii_reg; 1109082eeacSAndy Fleming 1119082eeacSAndy Fleming mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_STATUS); 1129082eeacSAndy Fleming 1139082eeacSAndy Fleming if ((mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) && 1149082eeacSAndy Fleming !(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) { 1159082eeacSAndy Fleming int i = 0; 1169082eeacSAndy Fleming 1179082eeacSAndy Fleming puts("Waiting for PHY realtime link"); 1189082eeacSAndy Fleming while (!(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) { 1199082eeacSAndy Fleming /* Timeout reached ? */ 1209082eeacSAndy Fleming if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 1219082eeacSAndy Fleming puts(" TIMEOUT !\n"); 1229082eeacSAndy Fleming phydev->link = 0; 1239082eeacSAndy Fleming break; 1249082eeacSAndy Fleming } 1259082eeacSAndy Fleming 1269082eeacSAndy Fleming if ((i++ % 1000) == 0) 1279082eeacSAndy Fleming putc('.'); 1289082eeacSAndy Fleming udelay(1000); 1299082eeacSAndy Fleming mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 1309082eeacSAndy Fleming MIIM_88E1xxx_PHY_STATUS); 1319082eeacSAndy Fleming } 1329082eeacSAndy Fleming puts(" done\n"); 1339082eeacSAndy Fleming udelay(500000); /* another 500 ms (results in faster booting) */ 1349082eeacSAndy Fleming } else { 1359082eeacSAndy Fleming if (mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) 1369082eeacSAndy Fleming phydev->link = 1; 1379082eeacSAndy Fleming else 1389082eeacSAndy Fleming phydev->link = 0; 1399082eeacSAndy Fleming } 1409082eeacSAndy Fleming 1419082eeacSAndy Fleming if (mii_reg & MIIM_88E1xxx_PHYSTAT_DUPLEX) 1429082eeacSAndy Fleming phydev->duplex = DUPLEX_FULL; 1439082eeacSAndy Fleming else 1449082eeacSAndy Fleming phydev->duplex = DUPLEX_HALF; 1459082eeacSAndy Fleming 1469082eeacSAndy Fleming speed = mii_reg & MIIM_88E1xxx_PHYSTAT_SPEED; 1479082eeacSAndy Fleming 1489082eeacSAndy Fleming switch (speed) { 1499082eeacSAndy Fleming case MIIM_88E1xxx_PHYSTAT_GBIT: 1509082eeacSAndy Fleming phydev->speed = SPEED_1000; 1519082eeacSAndy Fleming break; 1529082eeacSAndy Fleming case MIIM_88E1xxx_PHYSTAT_100: 1539082eeacSAndy Fleming phydev->speed = SPEED_100; 1549082eeacSAndy Fleming break; 1559082eeacSAndy Fleming default: 1569082eeacSAndy Fleming phydev->speed = SPEED_10; 1579082eeacSAndy Fleming break; 1589082eeacSAndy Fleming } 1599082eeacSAndy Fleming 1609082eeacSAndy Fleming return 0; 1619082eeacSAndy Fleming } 1629082eeacSAndy Fleming 1639082eeacSAndy Fleming static int m88e1011s_startup(struct phy_device *phydev) 1649082eeacSAndy Fleming { 1659082eeacSAndy Fleming genphy_update_link(phydev); 1669082eeacSAndy Fleming m88e1xxx_parse_status(phydev); 1679082eeacSAndy Fleming 1689082eeacSAndy Fleming return 0; 1699082eeacSAndy Fleming } 1709082eeacSAndy Fleming 1719082eeacSAndy Fleming /* Marvell 88E1111S */ 1729082eeacSAndy Fleming static int m88e1111s_config(struct phy_device *phydev) 1739082eeacSAndy Fleming { 1749082eeacSAndy Fleming int reg; 1759082eeacSAndy Fleming 1769082eeacSAndy Fleming if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 1779082eeacSAndy Fleming (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || 1789082eeacSAndy Fleming (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || 1799082eeacSAndy Fleming (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 180fa12a08eSZang Roy-R61911 reg = phy_read(phydev, 181fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); 182fa12a08eSZang Roy-R61911 if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 183fa12a08eSZang Roy-R61911 (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) { 184fa12a08eSZang Roy-R61911 reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY); 185fa12a08eSZang Roy-R61911 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 186fa12a08eSZang Roy-R61911 reg &= ~MIIM_88E1111_TX_DELAY; 187fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_RX_DELAY; 188fa12a08eSZang Roy-R61911 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 189fa12a08eSZang Roy-R61911 reg &= ~MIIM_88E1111_RX_DELAY; 190fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_TX_DELAY; 1919082eeacSAndy Fleming } 1929082eeacSAndy Fleming 193fa12a08eSZang Roy-R61911 phy_write(phydev, 194fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); 195fa12a08eSZang Roy-R61911 196fa12a08eSZang Roy-R61911 reg = phy_read(phydev, 197fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); 198fa12a08eSZang Roy-R61911 199fa12a08eSZang Roy-R61911 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); 200fa12a08eSZang Roy-R61911 201fa12a08eSZang Roy-R61911 if (reg & MIIM_88E1111_HWCFG_FIBER_COPPER_RES) 202fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_MODE_FIBER_RGMII; 203fa12a08eSZang Roy-R61911 else 204fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RGMII; 205fa12a08eSZang Roy-R61911 206fa12a08eSZang Roy-R61911 phy_write(phydev, 207fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg); 208fa12a08eSZang Roy-R61911 } 209fa12a08eSZang Roy-R61911 210fa12a08eSZang Roy-R61911 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { 211fa12a08eSZang Roy-R61911 reg = phy_read(phydev, 212fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); 213fa12a08eSZang Roy-R61911 214fa12a08eSZang Roy-R61911 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); 215fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK; 216fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; 217fa12a08eSZang Roy-R61911 218fa12a08eSZang Roy-R61911 phy_write(phydev, MDIO_DEVAD_NONE, 219fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR, reg); 220fa12a08eSZang Roy-R61911 } 221fa12a08eSZang Roy-R61911 222fa12a08eSZang Roy-R61911 if (phydev->interface == PHY_INTERFACE_MODE_RTBI) { 223fa12a08eSZang Roy-R61911 reg = phy_read(phydev, 224fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); 225fa12a08eSZang Roy-R61911 reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY); 226fa12a08eSZang Roy-R61911 phy_write(phydev, 227fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); 228fa12a08eSZang Roy-R61911 229fa12a08eSZang Roy-R61911 reg = phy_read(phydev, MDIO_DEVAD_NONE, 230fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR); 231fa12a08eSZang Roy-R61911 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | 232fa12a08eSZang Roy-R61911 MIIM_88E1111_HWCFG_FIBER_COPPER_RES); 233fa12a08eSZang Roy-R61911 reg |= 0x7 | MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; 234fa12a08eSZang Roy-R61911 phy_write(phydev, MDIO_DEVAD_NONE, 235fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR, reg); 236fa12a08eSZang Roy-R61911 237fa12a08eSZang Roy-R61911 /* soft reset */ 238*3089c47dSStefan Roese phy_reset(phydev); 239fa12a08eSZang Roy-R61911 240fa12a08eSZang Roy-R61911 reg = phy_read(phydev, MDIO_DEVAD_NONE, 241fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR); 242fa12a08eSZang Roy-R61911 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | 243fa12a08eSZang Roy-R61911 MIIM_88E1111_HWCFG_FIBER_COPPER_RES); 244fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RTBI | 245fa12a08eSZang Roy-R61911 MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; 246fa12a08eSZang Roy-R61911 phy_write(phydev, MDIO_DEVAD_NONE, 247fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR, reg); 248fa12a08eSZang Roy-R61911 } 249fa12a08eSZang Roy-R61911 250fa12a08eSZang Roy-R61911 /* soft reset */ 251*3089c47dSStefan Roese phy_reset(phydev); 2529082eeacSAndy Fleming 2539082eeacSAndy Fleming genphy_config_aneg(phydev); 2549082eeacSAndy Fleming 2559082eeacSAndy Fleming phy_reset(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 3539082eeacSAndy Fleming genphy_config_aneg(phydev); 3549082eeacSAndy Fleming 3559082eeacSAndy Fleming phy_reset(phydev); 3569082eeacSAndy Fleming 3579082eeacSAndy Fleming return 0; 3589082eeacSAndy Fleming } 3599082eeacSAndy Fleming 3609082eeacSAndy Fleming static int m88e1118_startup(struct phy_device *phydev) 3619082eeacSAndy Fleming { 3629082eeacSAndy Fleming /* Change Page Number */ 3639082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); 3649082eeacSAndy Fleming 3659082eeacSAndy Fleming genphy_update_link(phydev); 3669082eeacSAndy Fleming m88e1xxx_parse_status(phydev); 3679082eeacSAndy Fleming 3689082eeacSAndy Fleming return 0; 3699082eeacSAndy Fleming } 3709082eeacSAndy Fleming 3719082eeacSAndy Fleming /* Marvell 88E1121R */ 3729082eeacSAndy Fleming static int m88e1121_config(struct phy_device *phydev) 3739082eeacSAndy Fleming { 3749082eeacSAndy Fleming int pg; 3759082eeacSAndy Fleming 3769082eeacSAndy Fleming /* Configure the PHY */ 3779082eeacSAndy Fleming genphy_config_aneg(phydev); 3789082eeacSAndy Fleming 3799082eeacSAndy Fleming /* Switch the page to access the led register */ 3809082eeacSAndy Fleming pg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE); 3819082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, 3829082eeacSAndy Fleming MIIM_88E1121_PHY_LED_PAGE); 3839082eeacSAndy Fleming /* Configure leds */ 3849082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_LED_CTRL, 3859082eeacSAndy Fleming MIIM_88E1121_PHY_LED_DEF); 3869082eeacSAndy Fleming /* Restore the page pointer */ 3879082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, pg); 3889082eeacSAndy Fleming 3899082eeacSAndy Fleming /* Disable IRQs and de-assert interrupt */ 3909082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_EN, 0); 3919082eeacSAndy Fleming phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_STATUS); 3929082eeacSAndy Fleming 3939082eeacSAndy Fleming return 0; 3949082eeacSAndy Fleming } 3959082eeacSAndy Fleming 3969082eeacSAndy Fleming /* Marvell 88E1145 */ 3979082eeacSAndy Fleming static int m88e1145_config(struct phy_device *phydev) 3989082eeacSAndy Fleming { 3999082eeacSAndy Fleming int reg; 4009082eeacSAndy Fleming 4019082eeacSAndy Fleming /* Errata E0, E1 */ 4029082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x001b); 4039082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0x418f); 4049082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x0016); 4059082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0xa2da); 4069082eeacSAndy Fleming 4079082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_SCR, 4089082eeacSAndy Fleming MIIM_88E1xxx_PHY_MDI_X_AUTO); 4099082eeacSAndy Fleming 4109082eeacSAndy Fleming reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR); 4119082eeacSAndy Fleming if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 4129082eeacSAndy Fleming reg |= MIIM_M88E1145_RGMII_RX_DELAY | 4139082eeacSAndy Fleming MIIM_M88E1145_RGMII_TX_DELAY; 4149082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg); 4159082eeacSAndy Fleming 4169082eeacSAndy Fleming genphy_config_aneg(phydev); 4179082eeacSAndy Fleming 4189082eeacSAndy Fleming phy_reset(phydev); 4199082eeacSAndy Fleming 4209082eeacSAndy Fleming return 0; 4219082eeacSAndy Fleming } 4229082eeacSAndy Fleming 4239082eeacSAndy Fleming static int m88e1145_startup(struct phy_device *phydev) 4249082eeacSAndy Fleming { 4259082eeacSAndy Fleming genphy_update_link(phydev); 4269082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_LED_CONTROL, 4279082eeacSAndy Fleming MIIM_88E1145_PHY_LED_DIRECT); 4289082eeacSAndy Fleming m88e1xxx_parse_status(phydev); 4299082eeacSAndy Fleming 4309082eeacSAndy Fleming return 0; 4319082eeacSAndy Fleming } 4329082eeacSAndy Fleming 4339082eeacSAndy Fleming /* Marvell 88E1149S */ 4349082eeacSAndy Fleming static int m88e1149_config(struct phy_device *phydev) 4359082eeacSAndy Fleming { 4369082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x1f); 4379082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c); 4389082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x5); 4399082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0); 4409082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100); 4419082eeacSAndy Fleming 4429082eeacSAndy Fleming genphy_config_aneg(phydev); 4439082eeacSAndy Fleming 4449082eeacSAndy Fleming phy_reset(phydev); 4459082eeacSAndy Fleming 4469082eeacSAndy Fleming return 0; 4479082eeacSAndy Fleming } 4489082eeacSAndy Fleming 449aeceec0dSSebastian Hesselbarth /* Marvell 88E1310 */ 450aeceec0dSSebastian Hesselbarth static int m88e1310_config(struct phy_device *phydev) 451aeceec0dSSebastian Hesselbarth { 452aeceec0dSSebastian Hesselbarth u16 reg; 453aeceec0dSSebastian Hesselbarth 454aeceec0dSSebastian Hesselbarth /* LED link and activity */ 455aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003); 456aeceec0dSSebastian Hesselbarth reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL); 457aeceec0dSSebastian Hesselbarth reg = (reg & ~0xf) | 0x1; 458aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL, reg); 459aeceec0dSSebastian Hesselbarth 460aeceec0dSSebastian Hesselbarth /* Set LED2/INT to INT mode, low active */ 461aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003); 462aeceec0dSSebastian Hesselbarth reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN); 463aeceec0dSSebastian Hesselbarth reg = (reg & 0x77ff) | 0x0880; 464aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN, reg); 465aeceec0dSSebastian Hesselbarth 466aeceec0dSSebastian Hesselbarth /* Set RGMII delay */ 467aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0002); 468aeceec0dSSebastian Hesselbarth reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL); 469aeceec0dSSebastian Hesselbarth reg |= 0x0030; 470aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL, reg); 471aeceec0dSSebastian Hesselbarth 472aeceec0dSSebastian Hesselbarth /* Ensure to return to page 0 */ 473aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000); 474aeceec0dSSebastian Hesselbarth 475aeceec0dSSebastian Hesselbarth genphy_config_aneg(phydev); 476aeceec0dSSebastian Hesselbarth phy_reset(phydev); 477aeceec0dSSebastian Hesselbarth 478aeceec0dSSebastian Hesselbarth return 0; 479aeceec0dSSebastian Hesselbarth } 4809082eeacSAndy Fleming 4819082eeacSAndy Fleming static struct phy_driver M88E1011S_driver = { 4829082eeacSAndy Fleming .name = "Marvell 88E1011S", 4839082eeacSAndy Fleming .uid = 0x1410c60, 4849082eeacSAndy Fleming .mask = 0xffffff0, 4859082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 4869082eeacSAndy Fleming .config = &m88e1011s_config, 4879082eeacSAndy Fleming .startup = &m88e1011s_startup, 4889082eeacSAndy Fleming .shutdown = &genphy_shutdown, 4899082eeacSAndy Fleming }; 4909082eeacSAndy Fleming 4919082eeacSAndy Fleming static struct phy_driver M88E1111S_driver = { 4929082eeacSAndy Fleming .name = "Marvell 88E1111S", 4939082eeacSAndy Fleming .uid = 0x1410cc0, 4949082eeacSAndy Fleming .mask = 0xffffff0, 4959082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 4969082eeacSAndy Fleming .config = &m88e1111s_config, 4979082eeacSAndy Fleming .startup = &m88e1011s_startup, 4989082eeacSAndy Fleming .shutdown = &genphy_shutdown, 4999082eeacSAndy Fleming }; 5009082eeacSAndy Fleming 5019082eeacSAndy Fleming static struct phy_driver M88E1118_driver = { 5029082eeacSAndy Fleming .name = "Marvell 88E1118", 5039082eeacSAndy Fleming .uid = 0x1410e10, 5049082eeacSAndy Fleming .mask = 0xffffff0, 5059082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 5069082eeacSAndy Fleming .config = &m88e1118_config, 5079082eeacSAndy Fleming .startup = &m88e1118_startup, 5089082eeacSAndy Fleming .shutdown = &genphy_shutdown, 5099082eeacSAndy Fleming }; 5109082eeacSAndy Fleming 511b4b81e83SMichal Simek static struct phy_driver M88E1118R_driver = { 512b4b81e83SMichal Simek .name = "Marvell 88E1118R", 513b4b81e83SMichal Simek .uid = 0x1410e40, 514b4b81e83SMichal Simek .mask = 0xffffff0, 515b4b81e83SMichal Simek .features = PHY_GBIT_FEATURES, 516b4b81e83SMichal Simek .config = &m88e1118_config, 517b4b81e83SMichal Simek .startup = &m88e1118_startup, 518b4b81e83SMichal Simek .shutdown = &genphy_shutdown, 519b4b81e83SMichal Simek }; 520b4b81e83SMichal Simek 5219082eeacSAndy Fleming static struct phy_driver M88E1121R_driver = { 5229082eeacSAndy Fleming .name = "Marvell 88E1121R", 5239082eeacSAndy Fleming .uid = 0x1410cb0, 5249082eeacSAndy Fleming .mask = 0xffffff0, 5259082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 5269082eeacSAndy Fleming .config = &m88e1121_config, 5279082eeacSAndy Fleming .startup = &genphy_startup, 5289082eeacSAndy Fleming .shutdown = &genphy_shutdown, 5299082eeacSAndy Fleming }; 5309082eeacSAndy Fleming 5319082eeacSAndy Fleming static struct phy_driver M88E1145_driver = { 5329082eeacSAndy Fleming .name = "Marvell 88E1145", 5339082eeacSAndy Fleming .uid = 0x1410cd0, 5349082eeacSAndy Fleming .mask = 0xffffff0, 5359082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 5369082eeacSAndy Fleming .config = &m88e1145_config, 5379082eeacSAndy Fleming .startup = &m88e1145_startup, 5389082eeacSAndy Fleming .shutdown = &genphy_shutdown, 5399082eeacSAndy Fleming }; 5409082eeacSAndy Fleming 5419082eeacSAndy Fleming static struct phy_driver M88E1149S_driver = { 5429082eeacSAndy Fleming .name = "Marvell 88E1149S", 5439082eeacSAndy Fleming .uid = 0x1410ca0, 5449082eeacSAndy Fleming .mask = 0xffffff0, 5459082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 5469082eeacSAndy Fleming .config = &m88e1149_config, 5479082eeacSAndy Fleming .startup = &m88e1011s_startup, 5489082eeacSAndy Fleming .shutdown = &genphy_shutdown, 5499082eeacSAndy Fleming }; 5509082eeacSAndy Fleming 5518396d0abSClemens Gruber static struct phy_driver M88E1510_driver = { 5528396d0abSClemens Gruber .name = "Marvell 88E1510", 5538396d0abSClemens Gruber .uid = 0x1410dd0, 5548396d0abSClemens Gruber .mask = 0xffffff0, 5558396d0abSClemens Gruber .features = PHY_GBIT_FEATURES, 5568396d0abSClemens Gruber .config = &m88e1510_config, 5578396d0abSClemens Gruber .startup = &m88e1011s_startup, 5588396d0abSClemens Gruber .shutdown = &genphy_shutdown, 5598396d0abSClemens Gruber }; 5608396d0abSClemens Gruber 5611415107eSMichal Simek static struct phy_driver M88E1518_driver = { 5621415107eSMichal Simek .name = "Marvell 88E1518", 5631415107eSMichal Simek .uid = 0x1410dd1, 5641415107eSMichal Simek .mask = 0xffffff0, 5651415107eSMichal Simek .features = PHY_GBIT_FEATURES, 56635fa0ddaSHao Zhang .config = &m88e1518_config, 5671415107eSMichal Simek .startup = &m88e1011s_startup, 5681415107eSMichal Simek .shutdown = &genphy_shutdown, 5691415107eSMichal Simek }; 5701415107eSMichal Simek 571aeceec0dSSebastian Hesselbarth static struct phy_driver M88E1310_driver = { 572aeceec0dSSebastian Hesselbarth .name = "Marvell 88E1310", 573aeceec0dSSebastian Hesselbarth .uid = 0x01410e90, 574aeceec0dSSebastian Hesselbarth .mask = 0xffffff0, 575aeceec0dSSebastian Hesselbarth .features = PHY_GBIT_FEATURES, 576aeceec0dSSebastian Hesselbarth .config = &m88e1310_config, 577aeceec0dSSebastian Hesselbarth .startup = &m88e1011s_startup, 578aeceec0dSSebastian Hesselbarth .shutdown = &genphy_shutdown, 579aeceec0dSSebastian Hesselbarth }; 580aeceec0dSSebastian Hesselbarth 5819082eeacSAndy Fleming int phy_marvell_init(void) 5829082eeacSAndy Fleming { 583aeceec0dSSebastian Hesselbarth phy_register(&M88E1310_driver); 5849082eeacSAndy Fleming phy_register(&M88E1149S_driver); 5859082eeacSAndy Fleming phy_register(&M88E1145_driver); 5869082eeacSAndy Fleming phy_register(&M88E1121R_driver); 5879082eeacSAndy Fleming phy_register(&M88E1118_driver); 588b4b81e83SMichal Simek phy_register(&M88E1118R_driver); 5899082eeacSAndy Fleming phy_register(&M88E1111S_driver); 5909082eeacSAndy Fleming phy_register(&M88E1011S_driver); 5918396d0abSClemens Gruber phy_register(&M88E1510_driver); 5921415107eSMichal Simek phy_register(&M88E1518_driver); 5939082eeacSAndy Fleming 5949082eeacSAndy Fleming return 0; 5959082eeacSAndy Fleming } 596