19082eeacSAndy Fleming /* 29082eeacSAndy Fleming * Marvell PHY drivers 39082eeacSAndy Fleming * 49082eeacSAndy Fleming * This program is free software; you can redistribute it and/or 59082eeacSAndy Fleming * modify it under the terms of the GNU General Public License as 69082eeacSAndy Fleming * published by the Free Software Foundation; either version 2 of 79082eeacSAndy Fleming * the License, or (at your option) any later version. 89082eeacSAndy Fleming * 99082eeacSAndy Fleming * This program is distributed in the hope that it will be useful, 109082eeacSAndy Fleming * but WITHOUT ANY WARRANTY; without even the implied warranty of 119082eeacSAndy Fleming * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 129082eeacSAndy Fleming * GNU General Public License for more details. 139082eeacSAndy Fleming * 149082eeacSAndy Fleming * You should have received a copy of the GNU General Public License 159082eeacSAndy Fleming * along with this program; if not, write to the Free Software 169082eeacSAndy Fleming * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 179082eeacSAndy Fleming * MA 02111-1307 USA 189082eeacSAndy Fleming * 199082eeacSAndy Fleming * Copyright 2010-2011 Freescale Semiconductor, Inc. 209082eeacSAndy Fleming * author Andy Fleming 219082eeacSAndy Fleming * 229082eeacSAndy Fleming */ 239082eeacSAndy Fleming #include <config.h> 249082eeacSAndy Fleming #include <common.h> 259082eeacSAndy Fleming #include <phy.h> 269082eeacSAndy Fleming 279082eeacSAndy Fleming #define PHY_AUTONEGOTIATE_TIMEOUT 5000 289082eeacSAndy Fleming 299082eeacSAndy Fleming /* 88E1011 PHY Status Register */ 309082eeacSAndy Fleming #define MIIM_88E1xxx_PHY_STATUS 0x11 319082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_SPEED 0xc000 329082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_GBIT 0x8000 339082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_100 0x4000 349082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_DUPLEX 0x2000 359082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_SPDDONE 0x0800 369082eeacSAndy Fleming #define MIIM_88E1xxx_PHYSTAT_LINK 0x0400 379082eeacSAndy Fleming 389082eeacSAndy Fleming #define MIIM_88E1xxx_PHY_SCR 0x10 399082eeacSAndy Fleming #define MIIM_88E1xxx_PHY_MDI_X_AUTO 0x0060 409082eeacSAndy Fleming 419082eeacSAndy Fleming /* 88E1111 PHY LED Control Register */ 429082eeacSAndy Fleming #define MIIM_88E1111_PHY_LED_CONTROL 24 439082eeacSAndy Fleming #define MIIM_88E1111_PHY_LED_DIRECT 0x4100 449082eeacSAndy Fleming #define MIIM_88E1111_PHY_LED_COMBINE 0x411C 459082eeacSAndy Fleming 46fa12a08eSZang Roy-R61911 /* 88E1111 Extended PHY Specific Control Register */ 47fa12a08eSZang Roy-R61911 #define MIIM_88E1111_PHY_EXT_CR 0x14 48fa12a08eSZang Roy-R61911 #define MIIM_88E1111_RX_DELAY 0x80 49fa12a08eSZang Roy-R61911 #define MIIM_88E1111_TX_DELAY 0x2 50fa12a08eSZang Roy-R61911 51fa12a08eSZang Roy-R61911 /* 88E1111 Extended PHY Specific Status Register */ 52fa12a08eSZang Roy-R61911 #define MIIM_88E1111_PHY_EXT_SR 0x1b 53fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_MASK 0xf 54fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_COPPER_RGMII 0xb 55fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_FIBER_RGMII 0x3 56fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK 0x4 57fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_MODE_COPPER_RTBI 0x9 58fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO 0x8000 59fa12a08eSZang Roy-R61911 #define MIIM_88E1111_HWCFG_FIBER_COPPER_RES 0x2000 60fa12a08eSZang Roy-R61911 61fa12a08eSZang Roy-R61911 #define MIIM_88E1111_COPPER 0 62fa12a08eSZang Roy-R61911 #define MIIM_88E1111_FIBER 1 63fa12a08eSZang Roy-R61911 649082eeacSAndy Fleming /* 88E1118 PHY defines */ 659082eeacSAndy Fleming #define MIIM_88E1118_PHY_PAGE 22 669082eeacSAndy Fleming #define MIIM_88E1118_PHY_LED_PAGE 3 679082eeacSAndy Fleming 689082eeacSAndy Fleming /* 88E1121 PHY LED Control Register */ 699082eeacSAndy Fleming #define MIIM_88E1121_PHY_LED_CTRL 16 709082eeacSAndy Fleming #define MIIM_88E1121_PHY_LED_PAGE 3 719082eeacSAndy Fleming #define MIIM_88E1121_PHY_LED_DEF 0x0030 729082eeacSAndy Fleming 739082eeacSAndy Fleming /* 88E1121 PHY IRQ Enable/Status Register */ 749082eeacSAndy Fleming #define MIIM_88E1121_PHY_IRQ_EN 18 759082eeacSAndy Fleming #define MIIM_88E1121_PHY_IRQ_STATUS 19 769082eeacSAndy Fleming 779082eeacSAndy Fleming #define MIIM_88E1121_PHY_PAGE 22 789082eeacSAndy Fleming 799082eeacSAndy Fleming /* 88E1145 Extended PHY Specific Control Register */ 809082eeacSAndy Fleming #define MIIM_88E1145_PHY_EXT_CR 20 819082eeacSAndy Fleming #define MIIM_M88E1145_RGMII_RX_DELAY 0x0080 829082eeacSAndy Fleming #define MIIM_M88E1145_RGMII_TX_DELAY 0x0002 839082eeacSAndy Fleming 849082eeacSAndy Fleming #define MIIM_88E1145_PHY_LED_CONTROL 24 859082eeacSAndy Fleming #define MIIM_88E1145_PHY_LED_DIRECT 0x4100 869082eeacSAndy Fleming 879082eeacSAndy Fleming #define MIIM_88E1145_PHY_PAGE 29 889082eeacSAndy Fleming #define MIIM_88E1145_PHY_CAL_OV 30 899082eeacSAndy Fleming 909082eeacSAndy Fleming #define MIIM_88E1149_PHY_PAGE 29 919082eeacSAndy Fleming 92*aeceec0dSSebastian Hesselbarth /* 88E1310 PHY defines */ 93*aeceec0dSSebastian Hesselbarth #define MIIM_88E1310_PHY_LED_CTRL 16 94*aeceec0dSSebastian Hesselbarth #define MIIM_88E1310_PHY_IRQ_EN 18 95*aeceec0dSSebastian Hesselbarth #define MIIM_88E1310_PHY_RGMII_CTRL 21 96*aeceec0dSSebastian Hesselbarth #define MIIM_88E1310_PHY_PAGE 22 97*aeceec0dSSebastian Hesselbarth 989082eeacSAndy Fleming /* Marvell 88E1011S */ 999082eeacSAndy Fleming static int m88e1011s_config(struct phy_device *phydev) 1009082eeacSAndy Fleming { 1019082eeacSAndy Fleming /* Reset and configure the PHY */ 1029082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 1039082eeacSAndy Fleming 1049082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f); 1059082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c); 1069082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5); 1079082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0); 1089082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100); 1099082eeacSAndy Fleming 1109082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 1119082eeacSAndy Fleming 1129082eeacSAndy Fleming genphy_config_aneg(phydev); 1139082eeacSAndy Fleming 1149082eeacSAndy Fleming return 0; 1159082eeacSAndy Fleming } 1169082eeacSAndy Fleming 1179082eeacSAndy Fleming /* Parse the 88E1011's status register for speed and duplex 1189082eeacSAndy Fleming * information 1199082eeacSAndy Fleming */ 1209082eeacSAndy Fleming static uint m88e1xxx_parse_status(struct phy_device *phydev) 1219082eeacSAndy Fleming { 1229082eeacSAndy Fleming unsigned int speed; 1239082eeacSAndy Fleming unsigned int mii_reg; 1249082eeacSAndy Fleming 1259082eeacSAndy Fleming mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_STATUS); 1269082eeacSAndy Fleming 1279082eeacSAndy Fleming if ((mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) && 1289082eeacSAndy Fleming !(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) { 1299082eeacSAndy Fleming int i = 0; 1309082eeacSAndy Fleming 1319082eeacSAndy Fleming puts("Waiting for PHY realtime link"); 1329082eeacSAndy Fleming while (!(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) { 1339082eeacSAndy Fleming /* Timeout reached ? */ 1349082eeacSAndy Fleming if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 1359082eeacSAndy Fleming puts(" TIMEOUT !\n"); 1369082eeacSAndy Fleming phydev->link = 0; 1379082eeacSAndy Fleming break; 1389082eeacSAndy Fleming } 1399082eeacSAndy Fleming 1409082eeacSAndy Fleming if ((i++ % 1000) == 0) 1419082eeacSAndy Fleming putc('.'); 1429082eeacSAndy Fleming udelay(1000); 1439082eeacSAndy Fleming mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 1449082eeacSAndy Fleming MIIM_88E1xxx_PHY_STATUS); 1459082eeacSAndy Fleming } 1469082eeacSAndy Fleming puts(" done\n"); 1479082eeacSAndy Fleming udelay(500000); /* another 500 ms (results in faster booting) */ 1489082eeacSAndy Fleming } else { 1499082eeacSAndy Fleming if (mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) 1509082eeacSAndy Fleming phydev->link = 1; 1519082eeacSAndy Fleming else 1529082eeacSAndy Fleming phydev->link = 0; 1539082eeacSAndy Fleming } 1549082eeacSAndy Fleming 1559082eeacSAndy Fleming if (mii_reg & MIIM_88E1xxx_PHYSTAT_DUPLEX) 1569082eeacSAndy Fleming phydev->duplex = DUPLEX_FULL; 1579082eeacSAndy Fleming else 1589082eeacSAndy Fleming phydev->duplex = DUPLEX_HALF; 1599082eeacSAndy Fleming 1609082eeacSAndy Fleming speed = mii_reg & MIIM_88E1xxx_PHYSTAT_SPEED; 1619082eeacSAndy Fleming 1629082eeacSAndy Fleming switch (speed) { 1639082eeacSAndy Fleming case MIIM_88E1xxx_PHYSTAT_GBIT: 1649082eeacSAndy Fleming phydev->speed = SPEED_1000; 1659082eeacSAndy Fleming break; 1669082eeacSAndy Fleming case MIIM_88E1xxx_PHYSTAT_100: 1679082eeacSAndy Fleming phydev->speed = SPEED_100; 1689082eeacSAndy Fleming break; 1699082eeacSAndy Fleming default: 1709082eeacSAndy Fleming phydev->speed = SPEED_10; 1719082eeacSAndy Fleming break; 1729082eeacSAndy Fleming } 1739082eeacSAndy Fleming 1749082eeacSAndy Fleming return 0; 1759082eeacSAndy Fleming } 1769082eeacSAndy Fleming 1779082eeacSAndy Fleming static int m88e1011s_startup(struct phy_device *phydev) 1789082eeacSAndy Fleming { 1799082eeacSAndy Fleming genphy_update_link(phydev); 1809082eeacSAndy Fleming m88e1xxx_parse_status(phydev); 1819082eeacSAndy Fleming 1829082eeacSAndy Fleming return 0; 1839082eeacSAndy Fleming } 1849082eeacSAndy Fleming 1859082eeacSAndy Fleming /* Marvell 88E1111S */ 1869082eeacSAndy Fleming static int m88e1111s_config(struct phy_device *phydev) 1879082eeacSAndy Fleming { 1889082eeacSAndy Fleming int reg; 189fa12a08eSZang Roy-R61911 int timeout; 1909082eeacSAndy Fleming 1919082eeacSAndy Fleming if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 1929082eeacSAndy Fleming (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || 1939082eeacSAndy Fleming (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || 1949082eeacSAndy Fleming (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 195fa12a08eSZang Roy-R61911 reg = phy_read(phydev, 196fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); 197fa12a08eSZang Roy-R61911 if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 198fa12a08eSZang Roy-R61911 (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) { 199fa12a08eSZang Roy-R61911 reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY); 200fa12a08eSZang Roy-R61911 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 201fa12a08eSZang Roy-R61911 reg &= ~MIIM_88E1111_TX_DELAY; 202fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_RX_DELAY; 203fa12a08eSZang Roy-R61911 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 204fa12a08eSZang Roy-R61911 reg &= ~MIIM_88E1111_RX_DELAY; 205fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_TX_DELAY; 2069082eeacSAndy Fleming } 2079082eeacSAndy Fleming 208fa12a08eSZang Roy-R61911 phy_write(phydev, 209fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); 210fa12a08eSZang Roy-R61911 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 216fa12a08eSZang Roy-R61911 if (reg & MIIM_88E1111_HWCFG_FIBER_COPPER_RES) 217fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_MODE_FIBER_RGMII; 218fa12a08eSZang Roy-R61911 else 219fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RGMII; 220fa12a08eSZang Roy-R61911 221fa12a08eSZang Roy-R61911 phy_write(phydev, 222fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg); 223fa12a08eSZang Roy-R61911 } 224fa12a08eSZang Roy-R61911 225fa12a08eSZang Roy-R61911 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { 226fa12a08eSZang Roy-R61911 reg = phy_read(phydev, 227fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR); 228fa12a08eSZang Roy-R61911 229fa12a08eSZang Roy-R61911 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK); 230fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK; 231fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; 232fa12a08eSZang Roy-R61911 233fa12a08eSZang Roy-R61911 phy_write(phydev, MDIO_DEVAD_NONE, 234fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR, reg); 235fa12a08eSZang Roy-R61911 } 236fa12a08eSZang Roy-R61911 237fa12a08eSZang Roy-R61911 if (phydev->interface == PHY_INTERFACE_MODE_RTBI) { 238fa12a08eSZang Roy-R61911 reg = phy_read(phydev, 239fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR); 240fa12a08eSZang Roy-R61911 reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY); 241fa12a08eSZang Roy-R61911 phy_write(phydev, 242fa12a08eSZang Roy-R61911 MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg); 243fa12a08eSZang Roy-R61911 244fa12a08eSZang Roy-R61911 reg = phy_read(phydev, MDIO_DEVAD_NONE, 245fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR); 246fa12a08eSZang Roy-R61911 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | 247fa12a08eSZang Roy-R61911 MIIM_88E1111_HWCFG_FIBER_COPPER_RES); 248fa12a08eSZang Roy-R61911 reg |= 0x7 | MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; 249fa12a08eSZang Roy-R61911 phy_write(phydev, MDIO_DEVAD_NONE, 250fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR, reg); 251fa12a08eSZang Roy-R61911 252fa12a08eSZang Roy-R61911 /* soft reset */ 253fa12a08eSZang Roy-R61911 timeout = 1000; 254fa12a08eSZang Roy-R61911 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 255fa12a08eSZang Roy-R61911 udelay(1000); 256fa12a08eSZang Roy-R61911 reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 257fa12a08eSZang Roy-R61911 while ((reg & BMCR_RESET) && --timeout) { 258fa12a08eSZang Roy-R61911 udelay(1000); 259fa12a08eSZang Roy-R61911 reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 260fa12a08eSZang Roy-R61911 } 261fa12a08eSZang Roy-R61911 if (!timeout) 262fa12a08eSZang Roy-R61911 printf("%s: phy soft reset timeout\n", __func__); 263fa12a08eSZang Roy-R61911 264fa12a08eSZang Roy-R61911 reg = phy_read(phydev, MDIO_DEVAD_NONE, 265fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR); 266fa12a08eSZang Roy-R61911 reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK | 267fa12a08eSZang Roy-R61911 MIIM_88E1111_HWCFG_FIBER_COPPER_RES); 268fa12a08eSZang Roy-R61911 reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RTBI | 269fa12a08eSZang Roy-R61911 MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO; 270fa12a08eSZang Roy-R61911 phy_write(phydev, MDIO_DEVAD_NONE, 271fa12a08eSZang Roy-R61911 MIIM_88E1111_PHY_EXT_SR, reg); 272fa12a08eSZang Roy-R61911 } 273fa12a08eSZang Roy-R61911 274fa12a08eSZang Roy-R61911 /* soft reset */ 275fa12a08eSZang Roy-R61911 timeout = 1000; 276fa12a08eSZang Roy-R61911 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 277fa12a08eSZang Roy-R61911 udelay(1000); 278fa12a08eSZang Roy-R61911 reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 279fa12a08eSZang Roy-R61911 while ((reg & BMCR_RESET) && --timeout) { 280fa12a08eSZang Roy-R61911 udelay(1000); 281fa12a08eSZang Roy-R61911 reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 282fa12a08eSZang Roy-R61911 } 283fa12a08eSZang Roy-R61911 if (!timeout) 284fa12a08eSZang Roy-R61911 printf("%s: phy soft reset timeout\n", __func__); 2859082eeacSAndy Fleming 2869082eeacSAndy Fleming genphy_config_aneg(phydev); 2879082eeacSAndy Fleming 2889082eeacSAndy Fleming phy_reset(phydev); 2899082eeacSAndy Fleming 2909082eeacSAndy Fleming return 0; 2919082eeacSAndy Fleming } 2929082eeacSAndy Fleming 2939082eeacSAndy Fleming /* Marvell 88E1118 */ 2949082eeacSAndy Fleming static int m88e1118_config(struct phy_device *phydev) 2959082eeacSAndy Fleming { 2969082eeacSAndy Fleming /* Change Page Number */ 2979082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0002); 2989082eeacSAndy Fleming /* Delay RGMII TX and RX */ 2999082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x1070); 3009082eeacSAndy Fleming /* Change Page Number */ 3019082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0003); 3029082eeacSAndy Fleming /* Adjust LED control */ 3039082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x021e); 3049082eeacSAndy Fleming /* Change Page Number */ 3059082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); 3069082eeacSAndy Fleming 3079082eeacSAndy Fleming genphy_config_aneg(phydev); 3089082eeacSAndy Fleming 3099082eeacSAndy Fleming phy_reset(phydev); 3109082eeacSAndy Fleming 3119082eeacSAndy Fleming return 0; 3129082eeacSAndy Fleming } 3139082eeacSAndy Fleming 3149082eeacSAndy Fleming static int m88e1118_startup(struct phy_device *phydev) 3159082eeacSAndy Fleming { 3169082eeacSAndy Fleming /* Change Page Number */ 3179082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); 3189082eeacSAndy Fleming 3199082eeacSAndy Fleming genphy_update_link(phydev); 3209082eeacSAndy Fleming m88e1xxx_parse_status(phydev); 3219082eeacSAndy Fleming 3229082eeacSAndy Fleming return 0; 3239082eeacSAndy Fleming } 3249082eeacSAndy Fleming 3259082eeacSAndy Fleming /* Marvell 88E1121R */ 3269082eeacSAndy Fleming static int m88e1121_config(struct phy_device *phydev) 3279082eeacSAndy Fleming { 3289082eeacSAndy Fleming int pg; 3299082eeacSAndy Fleming 3309082eeacSAndy Fleming /* Configure the PHY */ 3319082eeacSAndy Fleming genphy_config_aneg(phydev); 3329082eeacSAndy Fleming 3339082eeacSAndy Fleming /* Switch the page to access the led register */ 3349082eeacSAndy Fleming pg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE); 3359082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, 3369082eeacSAndy Fleming MIIM_88E1121_PHY_LED_PAGE); 3379082eeacSAndy Fleming /* Configure leds */ 3389082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_LED_CTRL, 3399082eeacSAndy Fleming MIIM_88E1121_PHY_LED_DEF); 3409082eeacSAndy Fleming /* Restore the page pointer */ 3419082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, pg); 3429082eeacSAndy Fleming 3439082eeacSAndy Fleming /* Disable IRQs and de-assert interrupt */ 3449082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_EN, 0); 3459082eeacSAndy Fleming phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_STATUS); 3469082eeacSAndy Fleming 3479082eeacSAndy Fleming return 0; 3489082eeacSAndy Fleming } 3499082eeacSAndy Fleming 3509082eeacSAndy Fleming /* Marvell 88E1145 */ 3519082eeacSAndy Fleming static int m88e1145_config(struct phy_device *phydev) 3529082eeacSAndy Fleming { 3539082eeacSAndy Fleming int reg; 3549082eeacSAndy Fleming 3559082eeacSAndy Fleming /* Errata E0, E1 */ 3569082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x001b); 3579082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0x418f); 3589082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x0016); 3599082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0xa2da); 3609082eeacSAndy Fleming 3619082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_SCR, 3629082eeacSAndy Fleming MIIM_88E1xxx_PHY_MDI_X_AUTO); 3639082eeacSAndy Fleming 3649082eeacSAndy Fleming reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR); 3659082eeacSAndy Fleming if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 3669082eeacSAndy Fleming reg |= MIIM_M88E1145_RGMII_RX_DELAY | 3679082eeacSAndy Fleming MIIM_M88E1145_RGMII_TX_DELAY; 3689082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg); 3699082eeacSAndy Fleming 3709082eeacSAndy Fleming genphy_config_aneg(phydev); 3719082eeacSAndy Fleming 3729082eeacSAndy Fleming phy_reset(phydev); 3739082eeacSAndy Fleming 3749082eeacSAndy Fleming return 0; 3759082eeacSAndy Fleming } 3769082eeacSAndy Fleming 3779082eeacSAndy Fleming static int m88e1145_startup(struct phy_device *phydev) 3789082eeacSAndy Fleming { 3799082eeacSAndy Fleming genphy_update_link(phydev); 3809082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_LED_CONTROL, 3819082eeacSAndy Fleming MIIM_88E1145_PHY_LED_DIRECT); 3829082eeacSAndy Fleming m88e1xxx_parse_status(phydev); 3839082eeacSAndy Fleming 3849082eeacSAndy Fleming return 0; 3859082eeacSAndy Fleming } 3869082eeacSAndy Fleming 3879082eeacSAndy Fleming /* Marvell 88E1149S */ 3889082eeacSAndy Fleming static int m88e1149_config(struct phy_device *phydev) 3899082eeacSAndy Fleming { 3909082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x1f); 3919082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c); 3929082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x5); 3939082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0); 3949082eeacSAndy Fleming phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100); 3959082eeacSAndy Fleming 3969082eeacSAndy Fleming genphy_config_aneg(phydev); 3979082eeacSAndy Fleming 3989082eeacSAndy Fleming phy_reset(phydev); 3999082eeacSAndy Fleming 4009082eeacSAndy Fleming return 0; 4019082eeacSAndy Fleming } 4029082eeacSAndy Fleming 403*aeceec0dSSebastian Hesselbarth /* Marvell 88E1310 */ 404*aeceec0dSSebastian Hesselbarth static int m88e1310_config(struct phy_device *phydev) 405*aeceec0dSSebastian Hesselbarth { 406*aeceec0dSSebastian Hesselbarth u16 reg; 407*aeceec0dSSebastian Hesselbarth 408*aeceec0dSSebastian Hesselbarth /* LED link and activity */ 409*aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003); 410*aeceec0dSSebastian Hesselbarth reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL); 411*aeceec0dSSebastian Hesselbarth reg = (reg & ~0xf) | 0x1; 412*aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL, reg); 413*aeceec0dSSebastian Hesselbarth 414*aeceec0dSSebastian Hesselbarth /* Set LED2/INT to INT mode, low active */ 415*aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003); 416*aeceec0dSSebastian Hesselbarth reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN); 417*aeceec0dSSebastian Hesselbarth reg = (reg & 0x77ff) | 0x0880; 418*aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN, reg); 419*aeceec0dSSebastian Hesselbarth 420*aeceec0dSSebastian Hesselbarth /* Set RGMII delay */ 421*aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0002); 422*aeceec0dSSebastian Hesselbarth reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL); 423*aeceec0dSSebastian Hesselbarth reg |= 0x0030; 424*aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL, reg); 425*aeceec0dSSebastian Hesselbarth 426*aeceec0dSSebastian Hesselbarth /* Ensure to return to page 0 */ 427*aeceec0dSSebastian Hesselbarth phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000); 428*aeceec0dSSebastian Hesselbarth 429*aeceec0dSSebastian Hesselbarth genphy_config_aneg(phydev); 430*aeceec0dSSebastian Hesselbarth phy_reset(phydev); 431*aeceec0dSSebastian Hesselbarth 432*aeceec0dSSebastian Hesselbarth return 0; 433*aeceec0dSSebastian Hesselbarth } 4349082eeacSAndy Fleming 4359082eeacSAndy Fleming static struct phy_driver M88E1011S_driver = { 4369082eeacSAndy Fleming .name = "Marvell 88E1011S", 4379082eeacSAndy Fleming .uid = 0x1410c60, 4389082eeacSAndy Fleming .mask = 0xffffff0, 4399082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 4409082eeacSAndy Fleming .config = &m88e1011s_config, 4419082eeacSAndy Fleming .startup = &m88e1011s_startup, 4429082eeacSAndy Fleming .shutdown = &genphy_shutdown, 4439082eeacSAndy Fleming }; 4449082eeacSAndy Fleming 4459082eeacSAndy Fleming static struct phy_driver M88E1111S_driver = { 4469082eeacSAndy Fleming .name = "Marvell 88E1111S", 4479082eeacSAndy Fleming .uid = 0x1410cc0, 4489082eeacSAndy Fleming .mask = 0xffffff0, 4499082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 4509082eeacSAndy Fleming .config = &m88e1111s_config, 4519082eeacSAndy Fleming .startup = &m88e1011s_startup, 4529082eeacSAndy Fleming .shutdown = &genphy_shutdown, 4539082eeacSAndy Fleming }; 4549082eeacSAndy Fleming 4559082eeacSAndy Fleming static struct phy_driver M88E1118_driver = { 4569082eeacSAndy Fleming .name = "Marvell 88E1118", 4579082eeacSAndy Fleming .uid = 0x1410e10, 4589082eeacSAndy Fleming .mask = 0xffffff0, 4599082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 4609082eeacSAndy Fleming .config = &m88e1118_config, 4619082eeacSAndy Fleming .startup = &m88e1118_startup, 4629082eeacSAndy Fleming .shutdown = &genphy_shutdown, 4639082eeacSAndy Fleming }; 4649082eeacSAndy Fleming 465b4b81e83SMichal Simek static struct phy_driver M88E1118R_driver = { 466b4b81e83SMichal Simek .name = "Marvell 88E1118R", 467b4b81e83SMichal Simek .uid = 0x1410e40, 468b4b81e83SMichal Simek .mask = 0xffffff0, 469b4b81e83SMichal Simek .features = PHY_GBIT_FEATURES, 470b4b81e83SMichal Simek .config = &m88e1118_config, 471b4b81e83SMichal Simek .startup = &m88e1118_startup, 472b4b81e83SMichal Simek .shutdown = &genphy_shutdown, 473b4b81e83SMichal Simek }; 474b4b81e83SMichal Simek 4759082eeacSAndy Fleming static struct phy_driver M88E1121R_driver = { 4769082eeacSAndy Fleming .name = "Marvell 88E1121R", 4779082eeacSAndy Fleming .uid = 0x1410cb0, 4789082eeacSAndy Fleming .mask = 0xffffff0, 4799082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 4809082eeacSAndy Fleming .config = &m88e1121_config, 4819082eeacSAndy Fleming .startup = &genphy_startup, 4829082eeacSAndy Fleming .shutdown = &genphy_shutdown, 4839082eeacSAndy Fleming }; 4849082eeacSAndy Fleming 4859082eeacSAndy Fleming static struct phy_driver M88E1145_driver = { 4869082eeacSAndy Fleming .name = "Marvell 88E1145", 4879082eeacSAndy Fleming .uid = 0x1410cd0, 4889082eeacSAndy Fleming .mask = 0xffffff0, 4899082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 4909082eeacSAndy Fleming .config = &m88e1145_config, 4919082eeacSAndy Fleming .startup = &m88e1145_startup, 4929082eeacSAndy Fleming .shutdown = &genphy_shutdown, 4939082eeacSAndy Fleming }; 4949082eeacSAndy Fleming 4959082eeacSAndy Fleming static struct phy_driver M88E1149S_driver = { 4969082eeacSAndy Fleming .name = "Marvell 88E1149S", 4979082eeacSAndy Fleming .uid = 0x1410ca0, 4989082eeacSAndy Fleming .mask = 0xffffff0, 4999082eeacSAndy Fleming .features = PHY_GBIT_FEATURES, 5009082eeacSAndy Fleming .config = &m88e1149_config, 5019082eeacSAndy Fleming .startup = &m88e1011s_startup, 5029082eeacSAndy Fleming .shutdown = &genphy_shutdown, 5039082eeacSAndy Fleming }; 5049082eeacSAndy Fleming 5051415107eSMichal Simek static struct phy_driver M88E1518_driver = { 5061415107eSMichal Simek .name = "Marvell 88E1518", 5071415107eSMichal Simek .uid = 0x1410dd1, 5081415107eSMichal Simek .mask = 0xffffff0, 5091415107eSMichal Simek .features = PHY_GBIT_FEATURES, 5101415107eSMichal Simek .config = &m88e1111s_config, 5111415107eSMichal Simek .startup = &m88e1011s_startup, 5121415107eSMichal Simek .shutdown = &genphy_shutdown, 5131415107eSMichal Simek }; 5141415107eSMichal Simek 515*aeceec0dSSebastian Hesselbarth static struct phy_driver M88E1310_driver = { 516*aeceec0dSSebastian Hesselbarth .name = "Marvell 88E1310", 517*aeceec0dSSebastian Hesselbarth .uid = 0x01410e90, 518*aeceec0dSSebastian Hesselbarth .mask = 0xffffff0, 519*aeceec0dSSebastian Hesselbarth .features = PHY_GBIT_FEATURES, 520*aeceec0dSSebastian Hesselbarth .config = &m88e1310_config, 521*aeceec0dSSebastian Hesselbarth .startup = &m88e1011s_startup, 522*aeceec0dSSebastian Hesselbarth .shutdown = &genphy_shutdown, 523*aeceec0dSSebastian Hesselbarth }; 524*aeceec0dSSebastian Hesselbarth 5259082eeacSAndy Fleming int phy_marvell_init(void) 5269082eeacSAndy Fleming { 527*aeceec0dSSebastian Hesselbarth phy_register(&M88E1310_driver); 5289082eeacSAndy Fleming phy_register(&M88E1149S_driver); 5299082eeacSAndy Fleming phy_register(&M88E1145_driver); 5309082eeacSAndy Fleming phy_register(&M88E1121R_driver); 5319082eeacSAndy Fleming phy_register(&M88E1118_driver); 532b4b81e83SMichal Simek phy_register(&M88E1118R_driver); 5339082eeacSAndy Fleming phy_register(&M88E1111S_driver); 5349082eeacSAndy Fleming phy_register(&M88E1011S_driver); 5351415107eSMichal Simek phy_register(&M88E1518_driver); 5369082eeacSAndy Fleming 5379082eeacSAndy Fleming return 0; 5389082eeacSAndy Fleming } 539