100db8189SAndy Fleming /* 200db8189SAndy Fleming * drivers/net/phy/marvell.c 300db8189SAndy Fleming * 400db8189SAndy Fleming * Driver for Marvell PHYs 500db8189SAndy Fleming * 600db8189SAndy Fleming * Author: Andy Fleming 700db8189SAndy Fleming * 800db8189SAndy Fleming * Copyright (c) 2004 Freescale Semiconductor, Inc. 900db8189SAndy Fleming * 103871c387SMichael Stapelberg * Copyright (c) 2013 Michael Stapelberg <michael@stapelberg.de> 113871c387SMichael Stapelberg * 1200db8189SAndy Fleming * This program is free software; you can redistribute it and/or modify it 1300db8189SAndy Fleming * under the terms of the GNU General Public License as published by the 1400db8189SAndy Fleming * Free Software Foundation; either version 2 of the License, or (at your 1500db8189SAndy Fleming * option) any later version. 1600db8189SAndy Fleming * 1700db8189SAndy Fleming */ 1800db8189SAndy Fleming #include <linux/kernel.h> 1900db8189SAndy Fleming #include <linux/string.h> 2000db8189SAndy Fleming #include <linux/errno.h> 2100db8189SAndy Fleming #include <linux/unistd.h> 2200db8189SAndy Fleming #include <linux/interrupt.h> 2300db8189SAndy Fleming #include <linux/init.h> 2400db8189SAndy Fleming #include <linux/delay.h> 2500db8189SAndy Fleming #include <linux/netdevice.h> 2600db8189SAndy Fleming #include <linux/etherdevice.h> 2700db8189SAndy Fleming #include <linux/skbuff.h> 2800db8189SAndy Fleming #include <linux/spinlock.h> 2900db8189SAndy Fleming #include <linux/mm.h> 3000db8189SAndy Fleming #include <linux/module.h> 3100db8189SAndy Fleming #include <linux/mii.h> 3200db8189SAndy Fleming #include <linux/ethtool.h> 3300db8189SAndy Fleming #include <linux/phy.h> 342f495c39SBenjamin Herrenschmidt #include <linux/marvell_phy.h> 35cf41a51dSDavid Daney #include <linux/of.h> 3600db8189SAndy Fleming 37eea3b201SAvinash Kumar #include <linux/io.h> 3800db8189SAndy Fleming #include <asm/irq.h> 39eea3b201SAvinash Kumar #include <linux/uaccess.h> 4000db8189SAndy Fleming 4127d916d6SDavid Daney #define MII_MARVELL_PHY_PAGE 22 4227d916d6SDavid Daney 4300db8189SAndy Fleming #define MII_M1011_IEVENT 0x13 4400db8189SAndy Fleming #define MII_M1011_IEVENT_CLEAR 0x0000 4500db8189SAndy Fleming 4600db8189SAndy Fleming #define MII_M1011_IMASK 0x12 4700db8189SAndy Fleming #define MII_M1011_IMASK_INIT 0x6400 4800db8189SAndy Fleming #define MII_M1011_IMASK_CLEAR 0x0000 4900db8189SAndy Fleming 5076884679SAndy Fleming #define MII_M1011_PHY_SCR 0x10 5176884679SAndy Fleming #define MII_M1011_PHY_SCR_AUTO_CROSS 0x0060 5276884679SAndy Fleming 5376884679SAndy Fleming #define MII_M1145_PHY_EXT_CR 0x14 5476884679SAndy Fleming #define MII_M1145_RGMII_RX_DELAY 0x0080 5576884679SAndy Fleming #define MII_M1145_RGMII_TX_DELAY 0x0002 5676884679SAndy Fleming 5776884679SAndy Fleming #define MII_M1111_PHY_LED_CONTROL 0x18 5876884679SAndy Fleming #define MII_M1111_PHY_LED_DIRECT 0x4100 5976884679SAndy Fleming #define MII_M1111_PHY_LED_COMBINE 0x411c 60895ee682SKim Phillips #define MII_M1111_PHY_EXT_CR 0x14 61895ee682SKim Phillips #define MII_M1111_RX_DELAY 0x80 62895ee682SKim Phillips #define MII_M1111_TX_DELAY 0x2 63895ee682SKim Phillips #define MII_M1111_PHY_EXT_SR 0x1b 64be937f1fSAlexandr Smirnov 65895ee682SKim Phillips #define MII_M1111_HWCFG_MODE_MASK 0xf 66be937f1fSAlexandr Smirnov #define MII_M1111_HWCFG_MODE_COPPER_RGMII 0xb 67be937f1fSAlexandr Smirnov #define MII_M1111_HWCFG_MODE_FIBER_RGMII 0x3 684117b5beSKapil Juneja #define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4 695f8cbc13SLiu Yu-B13201 #define MII_M1111_HWCFG_MODE_COPPER_RTBI 0x9 70be937f1fSAlexandr Smirnov #define MII_M1111_HWCFG_FIBER_COPPER_AUTO 0x8000 71be937f1fSAlexandr Smirnov #define MII_M1111_HWCFG_FIBER_COPPER_RES 0x2000 72be937f1fSAlexandr Smirnov 73be937f1fSAlexandr Smirnov #define MII_M1111_COPPER 0 74be937f1fSAlexandr Smirnov #define MII_M1111_FIBER 1 75be937f1fSAlexandr Smirnov 76c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_PAGE 2 77c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_REG 21 78c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_RX_DELAY BIT(5) 79c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4) 80c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4)) 81c477d044SCyril Chemparathy 82337ac9d5SCyril Chemparathy #define MII_88E1318S_PHY_MSCR1_REG 16 83337ac9d5SCyril Chemparathy #define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6) 843ff1c259SCyril Chemparathy 853871c387SMichael Stapelberg /* Copper Specific Interrupt Enable Register */ 863871c387SMichael Stapelberg #define MII_88E1318S_PHY_CSIER 0x12 873871c387SMichael Stapelberg /* WOL Event Interrupt Enable */ 883871c387SMichael Stapelberg #define MII_88E1318S_PHY_CSIER_WOL_EIE BIT(7) 893871c387SMichael Stapelberg 903871c387SMichael Stapelberg /* LED Timer Control Register */ 913871c387SMichael Stapelberg #define MII_88E1318S_PHY_LED_PAGE 0x03 923871c387SMichael Stapelberg #define MII_88E1318S_PHY_LED_TCR 0x12 933871c387SMichael Stapelberg #define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15) 943871c387SMichael Stapelberg #define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7) 953871c387SMichael Stapelberg #define MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW BIT(11) 963871c387SMichael Stapelberg 973871c387SMichael Stapelberg /* Magic Packet MAC address registers */ 983871c387SMichael Stapelberg #define MII_88E1318S_PHY_MAGIC_PACKET_WORD2 0x17 993871c387SMichael Stapelberg #define MII_88E1318S_PHY_MAGIC_PACKET_WORD1 0x18 1003871c387SMichael Stapelberg #define MII_88E1318S_PHY_MAGIC_PACKET_WORD0 0x19 1013871c387SMichael Stapelberg 1023871c387SMichael Stapelberg #define MII_88E1318S_PHY_WOL_PAGE 0x11 1033871c387SMichael Stapelberg #define MII_88E1318S_PHY_WOL_CTRL 0x10 1043871c387SMichael Stapelberg #define MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS BIT(12) 1053871c387SMichael Stapelberg #define MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE BIT(14) 1063871c387SMichael Stapelberg 107140bc929SSergei Poselenov #define MII_88E1121_PHY_LED_CTRL 16 108140bc929SSergei Poselenov #define MII_88E1121_PHY_LED_PAGE 3 109140bc929SSergei Poselenov #define MII_88E1121_PHY_LED_DEF 0x0030 110140bc929SSergei Poselenov 111be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS 0x11 112be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_1000 0x8000 113be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_100 0x4000 114be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_SPD_MASK 0xc000 115be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000 116be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_RESOLVED 0x0800 117be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_LINK 0x0400 118be937f1fSAlexandr Smirnov 1193da09a51SMichal Simek #define MII_M1116R_CONTROL_REG_MAC 21 1203da09a51SMichal Simek 12176884679SAndy Fleming 12200db8189SAndy Fleming MODULE_DESCRIPTION("Marvell PHY driver"); 12300db8189SAndy Fleming MODULE_AUTHOR("Andy Fleming"); 12400db8189SAndy Fleming MODULE_LICENSE("GPL"); 12500db8189SAndy Fleming 12600db8189SAndy Fleming static int marvell_ack_interrupt(struct phy_device *phydev) 12700db8189SAndy Fleming { 12800db8189SAndy Fleming int err; 12900db8189SAndy Fleming 13000db8189SAndy Fleming /* Clear the interrupts by reading the reg */ 13100db8189SAndy Fleming err = phy_read(phydev, MII_M1011_IEVENT); 13200db8189SAndy Fleming 13300db8189SAndy Fleming if (err < 0) 13400db8189SAndy Fleming return err; 13500db8189SAndy Fleming 13600db8189SAndy Fleming return 0; 13700db8189SAndy Fleming } 13800db8189SAndy Fleming 13900db8189SAndy Fleming static int marvell_config_intr(struct phy_device *phydev) 14000db8189SAndy Fleming { 14100db8189SAndy Fleming int err; 14200db8189SAndy Fleming 14300db8189SAndy Fleming if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 14400db8189SAndy Fleming err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT); 14500db8189SAndy Fleming else 14600db8189SAndy Fleming err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); 14700db8189SAndy Fleming 14800db8189SAndy Fleming return err; 14900db8189SAndy Fleming } 15000db8189SAndy Fleming 15100db8189SAndy Fleming static int marvell_config_aneg(struct phy_device *phydev) 15200db8189SAndy Fleming { 15300db8189SAndy Fleming int err; 15400db8189SAndy Fleming 15500db8189SAndy Fleming /* The Marvell PHY has an errata which requires 15600db8189SAndy Fleming * that certain registers get written in order 15700db8189SAndy Fleming * to restart autonegotiation */ 15800db8189SAndy Fleming err = phy_write(phydev, MII_BMCR, BMCR_RESET); 15900db8189SAndy Fleming 16000db8189SAndy Fleming if (err < 0) 16100db8189SAndy Fleming return err; 16200db8189SAndy Fleming 16300db8189SAndy Fleming err = phy_write(phydev, 0x1d, 0x1f); 16400db8189SAndy Fleming if (err < 0) 16500db8189SAndy Fleming return err; 16600db8189SAndy Fleming 16700db8189SAndy Fleming err = phy_write(phydev, 0x1e, 0x200c); 16800db8189SAndy Fleming if (err < 0) 16900db8189SAndy Fleming return err; 17000db8189SAndy Fleming 17100db8189SAndy Fleming err = phy_write(phydev, 0x1d, 0x5); 17200db8189SAndy Fleming if (err < 0) 17300db8189SAndy Fleming return err; 17400db8189SAndy Fleming 17500db8189SAndy Fleming err = phy_write(phydev, 0x1e, 0); 17600db8189SAndy Fleming if (err < 0) 17700db8189SAndy Fleming return err; 17800db8189SAndy Fleming 17900db8189SAndy Fleming err = phy_write(phydev, 0x1e, 0x100); 18000db8189SAndy Fleming if (err < 0) 18100db8189SAndy Fleming return err; 18200db8189SAndy Fleming 18376884679SAndy Fleming err = phy_write(phydev, MII_M1011_PHY_SCR, 18476884679SAndy Fleming MII_M1011_PHY_SCR_AUTO_CROSS); 18576884679SAndy Fleming if (err < 0) 18676884679SAndy Fleming return err; 18776884679SAndy Fleming 18876884679SAndy Fleming err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL, 18976884679SAndy Fleming MII_M1111_PHY_LED_DIRECT); 19076884679SAndy Fleming if (err < 0) 19176884679SAndy Fleming return err; 19200db8189SAndy Fleming 19300db8189SAndy Fleming err = genphy_config_aneg(phydev); 1948ff44985SAnton Vorontsov if (err < 0) 19500db8189SAndy Fleming return err; 1968ff44985SAnton Vorontsov 1978ff44985SAnton Vorontsov if (phydev->autoneg != AUTONEG_ENABLE) { 1988ff44985SAnton Vorontsov int bmcr; 1998ff44985SAnton Vorontsov 2008ff44985SAnton Vorontsov /* 2018ff44985SAnton Vorontsov * A write to speed/duplex bits (that is performed by 2028ff44985SAnton Vorontsov * genphy_config_aneg() call above) must be followed by 2038ff44985SAnton Vorontsov * a software reset. Otherwise, the write has no effect. 2048ff44985SAnton Vorontsov */ 2058ff44985SAnton Vorontsov bmcr = phy_read(phydev, MII_BMCR); 2068ff44985SAnton Vorontsov if (bmcr < 0) 2078ff44985SAnton Vorontsov return bmcr; 2088ff44985SAnton Vorontsov 2098ff44985SAnton Vorontsov err = phy_write(phydev, MII_BMCR, bmcr | BMCR_RESET); 2108ff44985SAnton Vorontsov if (err < 0) 2118ff44985SAnton Vorontsov return err; 2128ff44985SAnton Vorontsov } 2138ff44985SAnton Vorontsov 2148ff44985SAnton Vorontsov return 0; 21500db8189SAndy Fleming } 21600db8189SAndy Fleming 217cf41a51dSDavid Daney #ifdef CONFIG_OF_MDIO 218cf41a51dSDavid Daney /* 219cf41a51dSDavid Daney * Set and/or override some configuration registers based on the 220cf41a51dSDavid Daney * marvell,reg-init property stored in the of_node for the phydev. 221cf41a51dSDavid Daney * 222cf41a51dSDavid Daney * marvell,reg-init = <reg-page reg mask value>,...; 223cf41a51dSDavid Daney * 224cf41a51dSDavid Daney * There may be one or more sets of <reg-page reg mask value>: 225cf41a51dSDavid Daney * 226cf41a51dSDavid Daney * reg-page: which register bank to use. 227cf41a51dSDavid Daney * reg: the register. 228cf41a51dSDavid Daney * mask: if non-zero, ANDed with existing register value. 229cf41a51dSDavid Daney * value: ORed with the masked value and written to the regiser. 230cf41a51dSDavid Daney * 231cf41a51dSDavid Daney */ 232cf41a51dSDavid Daney static int marvell_of_reg_init(struct phy_device *phydev) 233cf41a51dSDavid Daney { 234cf41a51dSDavid Daney const __be32 *paddr; 235cf41a51dSDavid Daney int len, i, saved_page, current_page, page_changed, ret; 236cf41a51dSDavid Daney 237cf41a51dSDavid Daney if (!phydev->dev.of_node) 238cf41a51dSDavid Daney return 0; 239cf41a51dSDavid Daney 240cf41a51dSDavid Daney paddr = of_get_property(phydev->dev.of_node, "marvell,reg-init", &len); 241cf41a51dSDavid Daney if (!paddr || len < (4 * sizeof(*paddr))) 242cf41a51dSDavid Daney return 0; 243cf41a51dSDavid Daney 244cf41a51dSDavid Daney saved_page = phy_read(phydev, MII_MARVELL_PHY_PAGE); 245cf41a51dSDavid Daney if (saved_page < 0) 246cf41a51dSDavid Daney return saved_page; 247cf41a51dSDavid Daney page_changed = 0; 248cf41a51dSDavid Daney current_page = saved_page; 249cf41a51dSDavid Daney 250cf41a51dSDavid Daney ret = 0; 251cf41a51dSDavid Daney len /= sizeof(*paddr); 252cf41a51dSDavid Daney for (i = 0; i < len - 3; i += 4) { 253cf41a51dSDavid Daney u16 reg_page = be32_to_cpup(paddr + i); 254cf41a51dSDavid Daney u16 reg = be32_to_cpup(paddr + i + 1); 255cf41a51dSDavid Daney u16 mask = be32_to_cpup(paddr + i + 2); 256cf41a51dSDavid Daney u16 val_bits = be32_to_cpup(paddr + i + 3); 257cf41a51dSDavid Daney int val; 258cf41a51dSDavid Daney 259cf41a51dSDavid Daney if (reg_page != current_page) { 260cf41a51dSDavid Daney current_page = reg_page; 261cf41a51dSDavid Daney page_changed = 1; 262cf41a51dSDavid Daney ret = phy_write(phydev, MII_MARVELL_PHY_PAGE, reg_page); 263cf41a51dSDavid Daney if (ret < 0) 264cf41a51dSDavid Daney goto err; 265cf41a51dSDavid Daney } 266cf41a51dSDavid Daney 267cf41a51dSDavid Daney val = 0; 268cf41a51dSDavid Daney if (mask) { 269cf41a51dSDavid Daney val = phy_read(phydev, reg); 270cf41a51dSDavid Daney if (val < 0) { 271cf41a51dSDavid Daney ret = val; 272cf41a51dSDavid Daney goto err; 273cf41a51dSDavid Daney } 274cf41a51dSDavid Daney val &= mask; 275cf41a51dSDavid Daney } 276cf41a51dSDavid Daney val |= val_bits; 277cf41a51dSDavid Daney 278cf41a51dSDavid Daney ret = phy_write(phydev, reg, val); 279cf41a51dSDavid Daney if (ret < 0) 280cf41a51dSDavid Daney goto err; 281cf41a51dSDavid Daney 282cf41a51dSDavid Daney } 283cf41a51dSDavid Daney err: 284cf41a51dSDavid Daney if (page_changed) { 285cf41a51dSDavid Daney i = phy_write(phydev, MII_MARVELL_PHY_PAGE, saved_page); 286cf41a51dSDavid Daney if (ret == 0) 287cf41a51dSDavid Daney ret = i; 288cf41a51dSDavid Daney } 289cf41a51dSDavid Daney return ret; 290cf41a51dSDavid Daney } 291cf41a51dSDavid Daney #else 292cf41a51dSDavid Daney static int marvell_of_reg_init(struct phy_device *phydev) 293cf41a51dSDavid Daney { 294cf41a51dSDavid Daney return 0; 295cf41a51dSDavid Daney } 296cf41a51dSDavid Daney #endif /* CONFIG_OF_MDIO */ 297cf41a51dSDavid Daney 298140bc929SSergei Poselenov static int m88e1121_config_aneg(struct phy_device *phydev) 299140bc929SSergei Poselenov { 300c477d044SCyril Chemparathy int err, oldpage, mscr; 301c477d044SCyril Chemparathy 30227d916d6SDavid Daney oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); 303c477d044SCyril Chemparathy 30427d916d6SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 305c477d044SCyril Chemparathy MII_88E1121_PHY_MSCR_PAGE); 306c477d044SCyril Chemparathy if (err < 0) 307c477d044SCyril Chemparathy return err; 308be8c6480SArnaud Patard 309be8c6480SArnaud Patard if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 310be8c6480SArnaud Patard (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || 311be8c6480SArnaud Patard (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || 312be8c6480SArnaud Patard (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 313be8c6480SArnaud Patard 314c477d044SCyril Chemparathy mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) & 315c477d044SCyril Chemparathy MII_88E1121_PHY_MSCR_DELAY_MASK; 316c477d044SCyril Chemparathy 317c477d044SCyril Chemparathy if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 318c477d044SCyril Chemparathy mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY | 319c477d044SCyril Chemparathy MII_88E1121_PHY_MSCR_TX_DELAY); 320c477d044SCyril Chemparathy else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) 321c477d044SCyril Chemparathy mscr |= MII_88E1121_PHY_MSCR_RX_DELAY; 322c477d044SCyril Chemparathy else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) 323c477d044SCyril Chemparathy mscr |= MII_88E1121_PHY_MSCR_TX_DELAY; 324c477d044SCyril Chemparathy 325c477d044SCyril Chemparathy err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr); 326c477d044SCyril Chemparathy if (err < 0) 327c477d044SCyril Chemparathy return err; 328be8c6480SArnaud Patard } 329c477d044SCyril Chemparathy 33027d916d6SDavid Daney phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage); 331140bc929SSergei Poselenov 332140bc929SSergei Poselenov err = phy_write(phydev, MII_BMCR, BMCR_RESET); 333140bc929SSergei Poselenov if (err < 0) 334140bc929SSergei Poselenov return err; 335140bc929SSergei Poselenov 336140bc929SSergei Poselenov err = phy_write(phydev, MII_M1011_PHY_SCR, 337140bc929SSergei Poselenov MII_M1011_PHY_SCR_AUTO_CROSS); 338140bc929SSergei Poselenov if (err < 0) 339140bc929SSergei Poselenov return err; 340140bc929SSergei Poselenov 34127d916d6SDavid Daney oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); 342140bc929SSergei Poselenov 34327d916d6SDavid Daney phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_88E1121_PHY_LED_PAGE); 344140bc929SSergei Poselenov phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF); 34527d916d6SDavid Daney phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage); 346140bc929SSergei Poselenov 347140bc929SSergei Poselenov err = genphy_config_aneg(phydev); 348140bc929SSergei Poselenov 349140bc929SSergei Poselenov return err; 350140bc929SSergei Poselenov } 351140bc929SSergei Poselenov 352337ac9d5SCyril Chemparathy static int m88e1318_config_aneg(struct phy_device *phydev) 3533ff1c259SCyril Chemparathy { 3543ff1c259SCyril Chemparathy int err, oldpage, mscr; 3553ff1c259SCyril Chemparathy 35627d916d6SDavid Daney oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); 3573ff1c259SCyril Chemparathy 35827d916d6SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 3593ff1c259SCyril Chemparathy MII_88E1121_PHY_MSCR_PAGE); 3603ff1c259SCyril Chemparathy if (err < 0) 3613ff1c259SCyril Chemparathy return err; 3623ff1c259SCyril Chemparathy 363337ac9d5SCyril Chemparathy mscr = phy_read(phydev, MII_88E1318S_PHY_MSCR1_REG); 364337ac9d5SCyril Chemparathy mscr |= MII_88E1318S_PHY_MSCR1_PAD_ODD; 3653ff1c259SCyril Chemparathy 366337ac9d5SCyril Chemparathy err = phy_write(phydev, MII_88E1318S_PHY_MSCR1_REG, mscr); 3673ff1c259SCyril Chemparathy if (err < 0) 3683ff1c259SCyril Chemparathy return err; 3693ff1c259SCyril Chemparathy 37027d916d6SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage); 3713ff1c259SCyril Chemparathy if (err < 0) 3723ff1c259SCyril Chemparathy return err; 3733ff1c259SCyril Chemparathy 3743ff1c259SCyril Chemparathy return m88e1121_config_aneg(phydev); 3753ff1c259SCyril Chemparathy } 3763ff1c259SCyril Chemparathy 37710e24caaSMichal Simek static int m88e1510_config_aneg(struct phy_device *phydev) 37810e24caaSMichal Simek { 37910e24caaSMichal Simek int err; 38010e24caaSMichal Simek 38110e24caaSMichal Simek err = m88e1318_config_aneg(phydev); 38210e24caaSMichal Simek if (err < 0) 38310e24caaSMichal Simek return err; 38410e24caaSMichal Simek 38510e24caaSMichal Simek return marvell_of_reg_init(phydev); 38610e24caaSMichal Simek } 38710e24caaSMichal Simek 3883da09a51SMichal Simek static int m88e1116r_config_init(struct phy_device *phydev) 3893da09a51SMichal Simek { 3903da09a51SMichal Simek int temp; 3913da09a51SMichal Simek int err; 3923da09a51SMichal Simek 3933da09a51SMichal Simek temp = phy_read(phydev, MII_BMCR); 3943da09a51SMichal Simek temp |= BMCR_RESET; 3953da09a51SMichal Simek err = phy_write(phydev, MII_BMCR, temp); 3963da09a51SMichal Simek if (err < 0) 3973da09a51SMichal Simek return err; 3983da09a51SMichal Simek 3993da09a51SMichal Simek mdelay(500); 4003da09a51SMichal Simek 4013da09a51SMichal Simek err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0); 4023da09a51SMichal Simek if (err < 0) 4033da09a51SMichal Simek return err; 4043da09a51SMichal Simek 4053da09a51SMichal Simek temp = phy_read(phydev, MII_M1011_PHY_SCR); 4063da09a51SMichal Simek temp |= (7 << 12); /* max number of gigabit attempts */ 4073da09a51SMichal Simek temp |= (1 << 11); /* enable downshift */ 4083da09a51SMichal Simek temp |= MII_M1011_PHY_SCR_AUTO_CROSS; 4093da09a51SMichal Simek err = phy_write(phydev, MII_M1011_PHY_SCR, temp); 4103da09a51SMichal Simek if (err < 0) 4113da09a51SMichal Simek return err; 4123da09a51SMichal Simek 4133da09a51SMichal Simek err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 2); 4143da09a51SMichal Simek if (err < 0) 4153da09a51SMichal Simek return err; 4163da09a51SMichal Simek temp = phy_read(phydev, MII_M1116R_CONTROL_REG_MAC); 4173da09a51SMichal Simek temp |= (1 << 5); 4183da09a51SMichal Simek temp |= (1 << 4); 4193da09a51SMichal Simek err = phy_write(phydev, MII_M1116R_CONTROL_REG_MAC, temp); 4203da09a51SMichal Simek if (err < 0) 4213da09a51SMichal Simek return err; 4223da09a51SMichal Simek err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0); 4233da09a51SMichal Simek if (err < 0) 4243da09a51SMichal Simek return err; 4253da09a51SMichal Simek 4263da09a51SMichal Simek temp = phy_read(phydev, MII_BMCR); 4273da09a51SMichal Simek temp |= BMCR_RESET; 4283da09a51SMichal Simek err = phy_write(phydev, MII_BMCR, temp); 4293da09a51SMichal Simek if (err < 0) 4303da09a51SMichal Simek return err; 4313da09a51SMichal Simek 4323da09a51SMichal Simek mdelay(500); 4333da09a51SMichal Simek 4343da09a51SMichal Simek return 0; 4353da09a51SMichal Simek } 4363da09a51SMichal Simek 437895ee682SKim Phillips static int m88e1111_config_init(struct phy_device *phydev) 438895ee682SKim Phillips { 439895ee682SKim Phillips int err; 440be937f1fSAlexandr Smirnov int temp; 441be937f1fSAlexandr Smirnov 442895ee682SKim Phillips if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 4439daf5a76SKim Phillips (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || 4449daf5a76SKim Phillips (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || 4459daf5a76SKim Phillips (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 446895ee682SKim Phillips 447895ee682SKim Phillips temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); 448895ee682SKim Phillips if (temp < 0) 449895ee682SKim Phillips return temp; 450895ee682SKim Phillips 4519daf5a76SKim Phillips if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { 452895ee682SKim Phillips temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); 4539daf5a76SKim Phillips } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 4549daf5a76SKim Phillips temp &= ~MII_M1111_TX_DELAY; 4559daf5a76SKim Phillips temp |= MII_M1111_RX_DELAY; 4569daf5a76SKim Phillips } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 4579daf5a76SKim Phillips temp &= ~MII_M1111_RX_DELAY; 4589daf5a76SKim Phillips temp |= MII_M1111_TX_DELAY; 4599daf5a76SKim Phillips } 460895ee682SKim Phillips 461895ee682SKim Phillips err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); 462895ee682SKim Phillips if (err < 0) 463895ee682SKim Phillips return err; 464895ee682SKim Phillips 465895ee682SKim Phillips temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 466895ee682SKim Phillips if (temp < 0) 467895ee682SKim Phillips return temp; 468895ee682SKim Phillips 469895ee682SKim Phillips temp &= ~(MII_M1111_HWCFG_MODE_MASK); 470be937f1fSAlexandr Smirnov 4717239016dSWang Jian if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES) 472be937f1fSAlexandr Smirnov temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII; 473be937f1fSAlexandr Smirnov else 474be937f1fSAlexandr Smirnov temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII; 475895ee682SKim Phillips 476895ee682SKim Phillips err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 477895ee682SKim Phillips if (err < 0) 478895ee682SKim Phillips return err; 479895ee682SKim Phillips } 480895ee682SKim Phillips 4814117b5beSKapil Juneja if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { 4824117b5beSKapil Juneja temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 4834117b5beSKapil Juneja if (temp < 0) 4844117b5beSKapil Juneja return temp; 4854117b5beSKapil Juneja 4864117b5beSKapil Juneja temp &= ~(MII_M1111_HWCFG_MODE_MASK); 4874117b5beSKapil Juneja temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK; 48832d0c1e1SHaiying Wang temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO; 4894117b5beSKapil Juneja 4904117b5beSKapil Juneja err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 4914117b5beSKapil Juneja if (err < 0) 4924117b5beSKapil Juneja return err; 4934117b5beSKapil Juneja } 4944117b5beSKapil Juneja 4955f8cbc13SLiu Yu-B13201 if (phydev->interface == PHY_INTERFACE_MODE_RTBI) { 4965f8cbc13SLiu Yu-B13201 temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); 4975f8cbc13SLiu Yu-B13201 if (temp < 0) 4985f8cbc13SLiu Yu-B13201 return temp; 4995f8cbc13SLiu Yu-B13201 temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); 5005f8cbc13SLiu Yu-B13201 err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); 5015f8cbc13SLiu Yu-B13201 if (err < 0) 5025f8cbc13SLiu Yu-B13201 return err; 5035f8cbc13SLiu Yu-B13201 5045f8cbc13SLiu Yu-B13201 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 5055f8cbc13SLiu Yu-B13201 if (temp < 0) 5065f8cbc13SLiu Yu-B13201 return temp; 5075f8cbc13SLiu Yu-B13201 temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES); 5085f8cbc13SLiu Yu-B13201 temp |= 0x7 | MII_M1111_HWCFG_FIBER_COPPER_AUTO; 5095f8cbc13SLiu Yu-B13201 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 5105f8cbc13SLiu Yu-B13201 if (err < 0) 5115f8cbc13SLiu Yu-B13201 return err; 5125f8cbc13SLiu Yu-B13201 5135f8cbc13SLiu Yu-B13201 /* soft reset */ 5145f8cbc13SLiu Yu-B13201 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 5155f8cbc13SLiu Yu-B13201 if (err < 0) 5165f8cbc13SLiu Yu-B13201 return err; 5175f8cbc13SLiu Yu-B13201 do 5185f8cbc13SLiu Yu-B13201 temp = phy_read(phydev, MII_BMCR); 5195f8cbc13SLiu Yu-B13201 while (temp & BMCR_RESET); 5205f8cbc13SLiu Yu-B13201 5215f8cbc13SLiu Yu-B13201 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 5225f8cbc13SLiu Yu-B13201 if (temp < 0) 5235f8cbc13SLiu Yu-B13201 return temp; 5245f8cbc13SLiu Yu-B13201 temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES); 5255f8cbc13SLiu Yu-B13201 temp |= MII_M1111_HWCFG_MODE_COPPER_RTBI | MII_M1111_HWCFG_FIBER_COPPER_AUTO; 5265f8cbc13SLiu Yu-B13201 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 5275f8cbc13SLiu Yu-B13201 if (err < 0) 5285f8cbc13SLiu Yu-B13201 return err; 5295f8cbc13SLiu Yu-B13201 } 5305f8cbc13SLiu Yu-B13201 531cf41a51dSDavid Daney err = marvell_of_reg_init(phydev); 532cf41a51dSDavid Daney if (err < 0) 533cf41a51dSDavid Daney return err; 5345f8cbc13SLiu Yu-B13201 535cc90cb3bSSrinivas Kandagatla return phy_write(phydev, MII_BMCR, BMCR_RESET); 536895ee682SKim Phillips } 537895ee682SKim Phillips 538605f196eSRon Madrid static int m88e1118_config_aneg(struct phy_device *phydev) 539605f196eSRon Madrid { 540605f196eSRon Madrid int err; 541605f196eSRon Madrid 542605f196eSRon Madrid err = phy_write(phydev, MII_BMCR, BMCR_RESET); 543605f196eSRon Madrid if (err < 0) 544605f196eSRon Madrid return err; 545605f196eSRon Madrid 546605f196eSRon Madrid err = phy_write(phydev, MII_M1011_PHY_SCR, 547605f196eSRon Madrid MII_M1011_PHY_SCR_AUTO_CROSS); 548605f196eSRon Madrid if (err < 0) 549605f196eSRon Madrid return err; 550605f196eSRon Madrid 551605f196eSRon Madrid err = genphy_config_aneg(phydev); 552605f196eSRon Madrid return 0; 553605f196eSRon Madrid } 554605f196eSRon Madrid 555605f196eSRon Madrid static int m88e1118_config_init(struct phy_device *phydev) 556605f196eSRon Madrid { 557605f196eSRon Madrid int err; 558605f196eSRon Madrid 559605f196eSRon Madrid /* Change address */ 56027d916d6SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0002); 561605f196eSRon Madrid if (err < 0) 562605f196eSRon Madrid return err; 563605f196eSRon Madrid 564605f196eSRon Madrid /* Enable 1000 Mbit */ 565605f196eSRon Madrid err = phy_write(phydev, 0x15, 0x1070); 566605f196eSRon Madrid if (err < 0) 567605f196eSRon Madrid return err; 568605f196eSRon Madrid 569605f196eSRon Madrid /* Change address */ 57027d916d6SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0003); 571605f196eSRon Madrid if (err < 0) 572605f196eSRon Madrid return err; 573605f196eSRon Madrid 574605f196eSRon Madrid /* Adjust LED Control */ 5752f495c39SBenjamin Herrenschmidt if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS) 5762f495c39SBenjamin Herrenschmidt err = phy_write(phydev, 0x10, 0x1100); 5772f495c39SBenjamin Herrenschmidt else 578605f196eSRon Madrid err = phy_write(phydev, 0x10, 0x021e); 579605f196eSRon Madrid if (err < 0) 580605f196eSRon Madrid return err; 581605f196eSRon Madrid 582cf41a51dSDavid Daney err = marvell_of_reg_init(phydev); 583cf41a51dSDavid Daney if (err < 0) 584cf41a51dSDavid Daney return err; 585cf41a51dSDavid Daney 586605f196eSRon Madrid /* Reset address */ 58727d916d6SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0); 588605f196eSRon Madrid if (err < 0) 589605f196eSRon Madrid return err; 590605f196eSRon Madrid 591cc90cb3bSSrinivas Kandagatla return phy_write(phydev, MII_BMCR, BMCR_RESET); 592605f196eSRon Madrid } 593605f196eSRon Madrid 59490600732SDavid Daney static int m88e1149_config_init(struct phy_device *phydev) 59590600732SDavid Daney { 59690600732SDavid Daney int err; 59790600732SDavid Daney 59890600732SDavid Daney /* Change address */ 59990600732SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0002); 60090600732SDavid Daney if (err < 0) 60190600732SDavid Daney return err; 60290600732SDavid Daney 60390600732SDavid Daney /* Enable 1000 Mbit */ 60490600732SDavid Daney err = phy_write(phydev, 0x15, 0x1048); 60590600732SDavid Daney if (err < 0) 60690600732SDavid Daney return err; 60790600732SDavid Daney 608cf41a51dSDavid Daney err = marvell_of_reg_init(phydev); 609cf41a51dSDavid Daney if (err < 0) 610cf41a51dSDavid Daney return err; 611cf41a51dSDavid Daney 61290600732SDavid Daney /* Reset address */ 61390600732SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0); 61490600732SDavid Daney if (err < 0) 61590600732SDavid Daney return err; 61690600732SDavid Daney 617cc90cb3bSSrinivas Kandagatla return phy_write(phydev, MII_BMCR, BMCR_RESET); 61890600732SDavid Daney } 61990600732SDavid Daney 62076884679SAndy Fleming static int m88e1145_config_init(struct phy_device *phydev) 62176884679SAndy Fleming { 62276884679SAndy Fleming int err; 62376884679SAndy Fleming 62476884679SAndy Fleming /* Take care of errata E0 & E1 */ 62576884679SAndy Fleming err = phy_write(phydev, 0x1d, 0x001b); 62676884679SAndy Fleming if (err < 0) 62776884679SAndy Fleming return err; 62876884679SAndy Fleming 62976884679SAndy Fleming err = phy_write(phydev, 0x1e, 0x418f); 63076884679SAndy Fleming if (err < 0) 63176884679SAndy Fleming return err; 63276884679SAndy Fleming 63376884679SAndy Fleming err = phy_write(phydev, 0x1d, 0x0016); 63476884679SAndy Fleming if (err < 0) 63576884679SAndy Fleming return err; 63676884679SAndy Fleming 63776884679SAndy Fleming err = phy_write(phydev, 0x1e, 0xa2da); 63876884679SAndy Fleming if (err < 0) 63976884679SAndy Fleming return err; 64076884679SAndy Fleming 641895ee682SKim Phillips if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { 64276884679SAndy Fleming int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR); 64376884679SAndy Fleming if (temp < 0) 64476884679SAndy Fleming return temp; 64576884679SAndy Fleming 64676884679SAndy Fleming temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY); 64776884679SAndy Fleming 64876884679SAndy Fleming err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp); 64976884679SAndy Fleming if (err < 0) 65076884679SAndy Fleming return err; 65176884679SAndy Fleming 6522f495c39SBenjamin Herrenschmidt if (phydev->dev_flags & MARVELL_PHY_M1145_FLAGS_RESISTANCE) { 65376884679SAndy Fleming err = phy_write(phydev, 0x1d, 0x0012); 65476884679SAndy Fleming if (err < 0) 65576884679SAndy Fleming return err; 65676884679SAndy Fleming 65776884679SAndy Fleming temp = phy_read(phydev, 0x1e); 65876884679SAndy Fleming if (temp < 0) 65976884679SAndy Fleming return temp; 66076884679SAndy Fleming 66176884679SAndy Fleming temp &= 0xf03f; 66276884679SAndy Fleming temp |= 2 << 9; /* 36 ohm */ 66376884679SAndy Fleming temp |= 2 << 6; /* 39 ohm */ 66476884679SAndy Fleming 66576884679SAndy Fleming err = phy_write(phydev, 0x1e, temp); 66676884679SAndy Fleming if (err < 0) 66776884679SAndy Fleming return err; 66876884679SAndy Fleming 66976884679SAndy Fleming err = phy_write(phydev, 0x1d, 0x3); 67076884679SAndy Fleming if (err < 0) 67176884679SAndy Fleming return err; 67276884679SAndy Fleming 67376884679SAndy Fleming err = phy_write(phydev, 0x1e, 0x8000); 67476884679SAndy Fleming if (err < 0) 67576884679SAndy Fleming return err; 67676884679SAndy Fleming } 67776884679SAndy Fleming } 67876884679SAndy Fleming 679cf41a51dSDavid Daney err = marvell_of_reg_init(phydev); 680cf41a51dSDavid Daney if (err < 0) 681cf41a51dSDavid Daney return err; 682cf41a51dSDavid Daney 68376884679SAndy Fleming return 0; 68476884679SAndy Fleming } 68500db8189SAndy Fleming 686be937f1fSAlexandr Smirnov /* marvell_read_status 687be937f1fSAlexandr Smirnov * 688be937f1fSAlexandr Smirnov * Generic status code does not detect Fiber correctly! 689be937f1fSAlexandr Smirnov * Description: 690be937f1fSAlexandr Smirnov * Check the link, then figure out the current state 691be937f1fSAlexandr Smirnov * by comparing what we advertise with what the link partner 692be937f1fSAlexandr Smirnov * advertises. Start by checking the gigabit possibilities, 693be937f1fSAlexandr Smirnov * then move on to 10/100. 694be937f1fSAlexandr Smirnov */ 695be937f1fSAlexandr Smirnov static int marvell_read_status(struct phy_device *phydev) 696be937f1fSAlexandr Smirnov { 697be937f1fSAlexandr Smirnov int adv; 698be937f1fSAlexandr Smirnov int err; 699be937f1fSAlexandr Smirnov int lpa; 700be937f1fSAlexandr Smirnov int status = 0; 701be937f1fSAlexandr Smirnov 702be937f1fSAlexandr Smirnov /* Update the link, but return if there 703be937f1fSAlexandr Smirnov * was an error */ 704be937f1fSAlexandr Smirnov err = genphy_update_link(phydev); 705be937f1fSAlexandr Smirnov if (err) 706be937f1fSAlexandr Smirnov return err; 707be937f1fSAlexandr Smirnov 708be937f1fSAlexandr Smirnov if (AUTONEG_ENABLE == phydev->autoneg) { 709be937f1fSAlexandr Smirnov status = phy_read(phydev, MII_M1011_PHY_STATUS); 710be937f1fSAlexandr Smirnov if (status < 0) 711be937f1fSAlexandr Smirnov return status; 712be937f1fSAlexandr Smirnov 713be937f1fSAlexandr Smirnov lpa = phy_read(phydev, MII_LPA); 714be937f1fSAlexandr Smirnov if (lpa < 0) 715be937f1fSAlexandr Smirnov return lpa; 716be937f1fSAlexandr Smirnov 717be937f1fSAlexandr Smirnov adv = phy_read(phydev, MII_ADVERTISE); 718be937f1fSAlexandr Smirnov if (adv < 0) 719be937f1fSAlexandr Smirnov return adv; 720be937f1fSAlexandr Smirnov 721be937f1fSAlexandr Smirnov lpa &= adv; 722be937f1fSAlexandr Smirnov 723be937f1fSAlexandr Smirnov if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) 724be937f1fSAlexandr Smirnov phydev->duplex = DUPLEX_FULL; 725be937f1fSAlexandr Smirnov else 726be937f1fSAlexandr Smirnov phydev->duplex = DUPLEX_HALF; 727be937f1fSAlexandr Smirnov 728be937f1fSAlexandr Smirnov status = status & MII_M1011_PHY_STATUS_SPD_MASK; 729be937f1fSAlexandr Smirnov phydev->pause = phydev->asym_pause = 0; 730be937f1fSAlexandr Smirnov 731be937f1fSAlexandr Smirnov switch (status) { 732be937f1fSAlexandr Smirnov case MII_M1011_PHY_STATUS_1000: 733be937f1fSAlexandr Smirnov phydev->speed = SPEED_1000; 734be937f1fSAlexandr Smirnov break; 735be937f1fSAlexandr Smirnov 736be937f1fSAlexandr Smirnov case MII_M1011_PHY_STATUS_100: 737be937f1fSAlexandr Smirnov phydev->speed = SPEED_100; 738be937f1fSAlexandr Smirnov break; 739be937f1fSAlexandr Smirnov 740be937f1fSAlexandr Smirnov default: 741be937f1fSAlexandr Smirnov phydev->speed = SPEED_10; 742be937f1fSAlexandr Smirnov break; 743be937f1fSAlexandr Smirnov } 744be937f1fSAlexandr Smirnov 745be937f1fSAlexandr Smirnov if (phydev->duplex == DUPLEX_FULL) { 746be937f1fSAlexandr Smirnov phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; 747be937f1fSAlexandr Smirnov phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; 748be937f1fSAlexandr Smirnov } 749be937f1fSAlexandr Smirnov } else { 750be937f1fSAlexandr Smirnov int bmcr = phy_read(phydev, MII_BMCR); 751be937f1fSAlexandr Smirnov 752be937f1fSAlexandr Smirnov if (bmcr < 0) 753be937f1fSAlexandr Smirnov return bmcr; 754be937f1fSAlexandr Smirnov 755be937f1fSAlexandr Smirnov if (bmcr & BMCR_FULLDPLX) 756be937f1fSAlexandr Smirnov phydev->duplex = DUPLEX_FULL; 757be937f1fSAlexandr Smirnov else 758be937f1fSAlexandr Smirnov phydev->duplex = DUPLEX_HALF; 759be937f1fSAlexandr Smirnov 760be937f1fSAlexandr Smirnov if (bmcr & BMCR_SPEED1000) 761be937f1fSAlexandr Smirnov phydev->speed = SPEED_1000; 762be937f1fSAlexandr Smirnov else if (bmcr & BMCR_SPEED100) 763be937f1fSAlexandr Smirnov phydev->speed = SPEED_100; 764be937f1fSAlexandr Smirnov else 765be937f1fSAlexandr Smirnov phydev->speed = SPEED_10; 766be937f1fSAlexandr Smirnov 767be937f1fSAlexandr Smirnov phydev->pause = phydev->asym_pause = 0; 768be937f1fSAlexandr Smirnov } 769be937f1fSAlexandr Smirnov 770be937f1fSAlexandr Smirnov return 0; 771be937f1fSAlexandr Smirnov } 772be937f1fSAlexandr Smirnov 773dcd07be3SAnatolij Gustschin static int m88e1121_did_interrupt(struct phy_device *phydev) 774dcd07be3SAnatolij Gustschin { 775dcd07be3SAnatolij Gustschin int imask; 776dcd07be3SAnatolij Gustschin 777dcd07be3SAnatolij Gustschin imask = phy_read(phydev, MII_M1011_IEVENT); 778dcd07be3SAnatolij Gustschin 779dcd07be3SAnatolij Gustschin if (imask & MII_M1011_IMASK_INIT) 780dcd07be3SAnatolij Gustschin return 1; 781dcd07be3SAnatolij Gustschin 782dcd07be3SAnatolij Gustschin return 0; 783dcd07be3SAnatolij Gustschin } 784dcd07be3SAnatolij Gustschin 7853871c387SMichael Stapelberg static void m88e1318_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) 7863871c387SMichael Stapelberg { 7873871c387SMichael Stapelberg wol->supported = WAKE_MAGIC; 7883871c387SMichael Stapelberg wol->wolopts = 0; 7893871c387SMichael Stapelberg 7903871c387SMichael Stapelberg if (phy_write(phydev, MII_MARVELL_PHY_PAGE, 7913871c387SMichael Stapelberg MII_88E1318S_PHY_WOL_PAGE) < 0) 7923871c387SMichael Stapelberg return; 7933871c387SMichael Stapelberg 7943871c387SMichael Stapelberg if (phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL) & 7953871c387SMichael Stapelberg MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE) 7963871c387SMichael Stapelberg wol->wolopts |= WAKE_MAGIC; 7973871c387SMichael Stapelberg 7983871c387SMichael Stapelberg if (phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x00) < 0) 7993871c387SMichael Stapelberg return; 8003871c387SMichael Stapelberg } 8013871c387SMichael Stapelberg 8023871c387SMichael Stapelberg static int m88e1318_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) 8033871c387SMichael Stapelberg { 8043871c387SMichael Stapelberg int err, oldpage, temp; 8053871c387SMichael Stapelberg 8063871c387SMichael Stapelberg oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); 8073871c387SMichael Stapelberg 8083871c387SMichael Stapelberg if (wol->wolopts & WAKE_MAGIC) { 8093871c387SMichael Stapelberg /* Explicitly switch to page 0x00, just to be sure */ 8103871c387SMichael Stapelberg err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x00); 8113871c387SMichael Stapelberg if (err < 0) 8123871c387SMichael Stapelberg return err; 8133871c387SMichael Stapelberg 8143871c387SMichael Stapelberg /* Enable the WOL interrupt */ 8153871c387SMichael Stapelberg temp = phy_read(phydev, MII_88E1318S_PHY_CSIER); 8163871c387SMichael Stapelberg temp |= MII_88E1318S_PHY_CSIER_WOL_EIE; 8173871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_CSIER, temp); 8183871c387SMichael Stapelberg if (err < 0) 8193871c387SMichael Stapelberg return err; 8203871c387SMichael Stapelberg 8213871c387SMichael Stapelberg err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 8223871c387SMichael Stapelberg MII_88E1318S_PHY_LED_PAGE); 8233871c387SMichael Stapelberg if (err < 0) 8243871c387SMichael Stapelberg return err; 8253871c387SMichael Stapelberg 8263871c387SMichael Stapelberg /* Setup LED[2] as interrupt pin (active low) */ 8273871c387SMichael Stapelberg temp = phy_read(phydev, MII_88E1318S_PHY_LED_TCR); 8283871c387SMichael Stapelberg temp &= ~MII_88E1318S_PHY_LED_TCR_FORCE_INT; 8293871c387SMichael Stapelberg temp |= MII_88E1318S_PHY_LED_TCR_INTn_ENABLE; 8303871c387SMichael Stapelberg temp |= MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW; 8313871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_LED_TCR, temp); 8323871c387SMichael Stapelberg if (err < 0) 8333871c387SMichael Stapelberg return err; 8343871c387SMichael Stapelberg 8353871c387SMichael Stapelberg err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 8363871c387SMichael Stapelberg MII_88E1318S_PHY_WOL_PAGE); 8373871c387SMichael Stapelberg if (err < 0) 8383871c387SMichael Stapelberg return err; 8393871c387SMichael Stapelberg 8403871c387SMichael Stapelberg /* Store the device address for the magic packet */ 8413871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD2, 8423871c387SMichael Stapelberg ((phydev->attached_dev->dev_addr[5] << 8) | 8433871c387SMichael Stapelberg phydev->attached_dev->dev_addr[4])); 8443871c387SMichael Stapelberg if (err < 0) 8453871c387SMichael Stapelberg return err; 8463871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD1, 8473871c387SMichael Stapelberg ((phydev->attached_dev->dev_addr[3] << 8) | 8483871c387SMichael Stapelberg phydev->attached_dev->dev_addr[2])); 8493871c387SMichael Stapelberg if (err < 0) 8503871c387SMichael Stapelberg return err; 8513871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD0, 8523871c387SMichael Stapelberg ((phydev->attached_dev->dev_addr[1] << 8) | 8533871c387SMichael Stapelberg phydev->attached_dev->dev_addr[0])); 8543871c387SMichael Stapelberg if (err < 0) 8553871c387SMichael Stapelberg return err; 8563871c387SMichael Stapelberg 8573871c387SMichael Stapelberg /* Clear WOL status and enable magic packet matching */ 8583871c387SMichael Stapelberg temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL); 8593871c387SMichael Stapelberg temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS; 8603871c387SMichael Stapelberg temp |= MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE; 8613871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp); 8623871c387SMichael Stapelberg if (err < 0) 8633871c387SMichael Stapelberg return err; 8643871c387SMichael Stapelberg } else { 8653871c387SMichael Stapelberg err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 8663871c387SMichael Stapelberg MII_88E1318S_PHY_WOL_PAGE); 8673871c387SMichael Stapelberg if (err < 0) 8683871c387SMichael Stapelberg return err; 8693871c387SMichael Stapelberg 8703871c387SMichael Stapelberg /* Clear WOL status and disable magic packet matching */ 8713871c387SMichael Stapelberg temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL); 8723871c387SMichael Stapelberg temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS; 8733871c387SMichael Stapelberg temp &= ~MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE; 8743871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp); 8753871c387SMichael Stapelberg if (err < 0) 8763871c387SMichael Stapelberg return err; 8773871c387SMichael Stapelberg } 8783871c387SMichael Stapelberg 8793871c387SMichael Stapelberg err = phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage); 8803871c387SMichael Stapelberg if (err < 0) 8813871c387SMichael Stapelberg return err; 8823871c387SMichael Stapelberg 8833871c387SMichael Stapelberg return 0; 8843871c387SMichael Stapelberg } 8853871c387SMichael Stapelberg 886e5479239SOlof Johansson static struct phy_driver marvell_drivers[] = { 887e5479239SOlof Johansson { 8882f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1101, 8892f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 89000db8189SAndy Fleming .name = "Marvell 88E1101", 89100db8189SAndy Fleming .features = PHY_GBIT_FEATURES, 89200db8189SAndy Fleming .flags = PHY_HAS_INTERRUPT, 89300db8189SAndy Fleming .config_aneg = &marvell_config_aneg, 89400db8189SAndy Fleming .read_status = &genphy_read_status, 89500db8189SAndy Fleming .ack_interrupt = &marvell_ack_interrupt, 89600db8189SAndy Fleming .config_intr = &marvell_config_intr, 8970898b448SSebastian Hesselbarth .resume = &genphy_resume, 8980898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 899ac8c635aSOlof Johansson .driver = { .owner = THIS_MODULE }, 900e5479239SOlof Johansson }, 901e5479239SOlof Johansson { 9022f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1112, 9032f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 90485cfb534SOlof Johansson .name = "Marvell 88E1112", 90585cfb534SOlof Johansson .features = PHY_GBIT_FEATURES, 90685cfb534SOlof Johansson .flags = PHY_HAS_INTERRUPT, 90785cfb534SOlof Johansson .config_init = &m88e1111_config_init, 90885cfb534SOlof Johansson .config_aneg = &marvell_config_aneg, 90985cfb534SOlof Johansson .read_status = &genphy_read_status, 91085cfb534SOlof Johansson .ack_interrupt = &marvell_ack_interrupt, 91185cfb534SOlof Johansson .config_intr = &marvell_config_intr, 9120898b448SSebastian Hesselbarth .resume = &genphy_resume, 9130898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 914ac8c635aSOlof Johansson .driver = { .owner = THIS_MODULE }, 91585cfb534SOlof Johansson }, 91685cfb534SOlof Johansson { 9172f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1111, 9182f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 91976884679SAndy Fleming .name = "Marvell 88E1111", 92076884679SAndy Fleming .features = PHY_GBIT_FEATURES, 92176884679SAndy Fleming .flags = PHY_HAS_INTERRUPT, 922e5479239SOlof Johansson .config_init = &m88e1111_config_init, 92376884679SAndy Fleming .config_aneg = &marvell_config_aneg, 924be937f1fSAlexandr Smirnov .read_status = &marvell_read_status, 92576884679SAndy Fleming .ack_interrupt = &marvell_ack_interrupt, 92676884679SAndy Fleming .config_intr = &marvell_config_intr, 9270898b448SSebastian Hesselbarth .resume = &genphy_resume, 9280898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 929ac8c635aSOlof Johansson .driver = { .owner = THIS_MODULE }, 930e5479239SOlof Johansson }, 931e5479239SOlof Johansson { 9322f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1118, 9332f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 934605f196eSRon Madrid .name = "Marvell 88E1118", 935605f196eSRon Madrid .features = PHY_GBIT_FEATURES, 936605f196eSRon Madrid .flags = PHY_HAS_INTERRUPT, 937605f196eSRon Madrid .config_init = &m88e1118_config_init, 938605f196eSRon Madrid .config_aneg = &m88e1118_config_aneg, 939605f196eSRon Madrid .read_status = &genphy_read_status, 940605f196eSRon Madrid .ack_interrupt = &marvell_ack_interrupt, 941605f196eSRon Madrid .config_intr = &marvell_config_intr, 9420898b448SSebastian Hesselbarth .resume = &genphy_resume, 9430898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 944605f196eSRon Madrid .driver = {.owner = THIS_MODULE,}, 945605f196eSRon Madrid }, 946605f196eSRon Madrid { 9472f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1121R, 9482f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 949140bc929SSergei Poselenov .name = "Marvell 88E1121R", 950140bc929SSergei Poselenov .features = PHY_GBIT_FEATURES, 951140bc929SSergei Poselenov .flags = PHY_HAS_INTERRUPT, 952140bc929SSergei Poselenov .config_aneg = &m88e1121_config_aneg, 953140bc929SSergei Poselenov .read_status = &marvell_read_status, 954140bc929SSergei Poselenov .ack_interrupt = &marvell_ack_interrupt, 955140bc929SSergei Poselenov .config_intr = &marvell_config_intr, 956dcd07be3SAnatolij Gustschin .did_interrupt = &m88e1121_did_interrupt, 9570898b448SSebastian Hesselbarth .resume = &genphy_resume, 9580898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 959140bc929SSergei Poselenov .driver = { .owner = THIS_MODULE }, 960140bc929SSergei Poselenov }, 961140bc929SSergei Poselenov { 962337ac9d5SCyril Chemparathy .phy_id = MARVELL_PHY_ID_88E1318S, 9636ba74014SLinus Torvalds .phy_id_mask = MARVELL_PHY_ID_MASK, 964337ac9d5SCyril Chemparathy .name = "Marvell 88E1318S", 9653ff1c259SCyril Chemparathy .features = PHY_GBIT_FEATURES, 9663ff1c259SCyril Chemparathy .flags = PHY_HAS_INTERRUPT, 967337ac9d5SCyril Chemparathy .config_aneg = &m88e1318_config_aneg, 9683ff1c259SCyril Chemparathy .read_status = &marvell_read_status, 9693ff1c259SCyril Chemparathy .ack_interrupt = &marvell_ack_interrupt, 9703ff1c259SCyril Chemparathy .config_intr = &marvell_config_intr, 9713ff1c259SCyril Chemparathy .did_interrupt = &m88e1121_did_interrupt, 9723871c387SMichael Stapelberg .get_wol = &m88e1318_get_wol, 9733871c387SMichael Stapelberg .set_wol = &m88e1318_set_wol, 9740898b448SSebastian Hesselbarth .resume = &genphy_resume, 9750898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 9763ff1c259SCyril Chemparathy .driver = { .owner = THIS_MODULE }, 9773ff1c259SCyril Chemparathy }, 9783ff1c259SCyril Chemparathy { 9792f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1145, 9802f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 98176884679SAndy Fleming .name = "Marvell 88E1145", 98276884679SAndy Fleming .features = PHY_GBIT_FEATURES, 98376884679SAndy Fleming .flags = PHY_HAS_INTERRUPT, 98476884679SAndy Fleming .config_init = &m88e1145_config_init, 98576884679SAndy Fleming .config_aneg = &marvell_config_aneg, 98676884679SAndy Fleming .read_status = &genphy_read_status, 98776884679SAndy Fleming .ack_interrupt = &marvell_ack_interrupt, 98876884679SAndy Fleming .config_intr = &marvell_config_intr, 9890898b448SSebastian Hesselbarth .resume = &genphy_resume, 9900898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 991ac8c635aSOlof Johansson .driver = { .owner = THIS_MODULE }, 992ac8c635aSOlof Johansson }, 993ac8c635aSOlof Johansson { 99490600732SDavid Daney .phy_id = MARVELL_PHY_ID_88E1149R, 99590600732SDavid Daney .phy_id_mask = MARVELL_PHY_ID_MASK, 99690600732SDavid Daney .name = "Marvell 88E1149R", 99790600732SDavid Daney .features = PHY_GBIT_FEATURES, 99890600732SDavid Daney .flags = PHY_HAS_INTERRUPT, 99990600732SDavid Daney .config_init = &m88e1149_config_init, 100090600732SDavid Daney .config_aneg = &m88e1118_config_aneg, 100190600732SDavid Daney .read_status = &genphy_read_status, 100290600732SDavid Daney .ack_interrupt = &marvell_ack_interrupt, 100390600732SDavid Daney .config_intr = &marvell_config_intr, 10040898b448SSebastian Hesselbarth .resume = &genphy_resume, 10050898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 100690600732SDavid Daney .driver = { .owner = THIS_MODULE }, 100790600732SDavid Daney }, 100890600732SDavid Daney { 10092f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1240, 10102f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 1011ac8c635aSOlof Johansson .name = "Marvell 88E1240", 1012ac8c635aSOlof Johansson .features = PHY_GBIT_FEATURES, 1013ac8c635aSOlof Johansson .flags = PHY_HAS_INTERRUPT, 1014ac8c635aSOlof Johansson .config_init = &m88e1111_config_init, 1015ac8c635aSOlof Johansson .config_aneg = &marvell_config_aneg, 1016ac8c635aSOlof Johansson .read_status = &genphy_read_status, 1017ac8c635aSOlof Johansson .ack_interrupt = &marvell_ack_interrupt, 1018ac8c635aSOlof Johansson .config_intr = &marvell_config_intr, 10190898b448SSebastian Hesselbarth .resume = &genphy_resume, 10200898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 1021ac8c635aSOlof Johansson .driver = { .owner = THIS_MODULE }, 1022ac8c635aSOlof Johansson }, 10233da09a51SMichal Simek { 10243da09a51SMichal Simek .phy_id = MARVELL_PHY_ID_88E1116R, 10253da09a51SMichal Simek .phy_id_mask = MARVELL_PHY_ID_MASK, 10263da09a51SMichal Simek .name = "Marvell 88E1116R", 10273da09a51SMichal Simek .features = PHY_GBIT_FEATURES, 10283da09a51SMichal Simek .flags = PHY_HAS_INTERRUPT, 10293da09a51SMichal Simek .config_init = &m88e1116r_config_init, 10303da09a51SMichal Simek .config_aneg = &genphy_config_aneg, 10313da09a51SMichal Simek .read_status = &genphy_read_status, 10323da09a51SMichal Simek .ack_interrupt = &marvell_ack_interrupt, 10333da09a51SMichal Simek .config_intr = &marvell_config_intr, 10340898b448SSebastian Hesselbarth .resume = &genphy_resume, 10350898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 10363da09a51SMichal Simek .driver = { .owner = THIS_MODULE }, 10373da09a51SMichal Simek }, 103810e24caaSMichal Simek { 103910e24caaSMichal Simek .phy_id = MARVELL_PHY_ID_88E1510, 104010e24caaSMichal Simek .phy_id_mask = MARVELL_PHY_ID_MASK, 104110e24caaSMichal Simek .name = "Marvell 88E1510", 104210e24caaSMichal Simek .features = PHY_GBIT_FEATURES, 104310e24caaSMichal Simek .flags = PHY_HAS_INTERRUPT, 104410e24caaSMichal Simek .config_aneg = &m88e1510_config_aneg, 104510e24caaSMichal Simek .read_status = &marvell_read_status, 104610e24caaSMichal Simek .ack_interrupt = &marvell_ack_interrupt, 104710e24caaSMichal Simek .config_intr = &marvell_config_intr, 104810e24caaSMichal Simek .did_interrupt = &m88e1121_did_interrupt, 10490898b448SSebastian Hesselbarth .resume = &genphy_resume, 10500898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 105110e24caaSMichal Simek .driver = { .owner = THIS_MODULE }, 105210e24caaSMichal Simek }, 105376884679SAndy Fleming }; 105476884679SAndy Fleming 105500db8189SAndy Fleming static int __init marvell_init(void) 105600db8189SAndy Fleming { 1057d5bf9071SChristian Hohnstaedt return phy_drivers_register(marvell_drivers, 1058d5bf9071SChristian Hohnstaedt ARRAY_SIZE(marvell_drivers)); 105900db8189SAndy Fleming } 106000db8189SAndy Fleming 106100db8189SAndy Fleming static void __exit marvell_exit(void) 106200db8189SAndy Fleming { 1063d5bf9071SChristian Hohnstaedt phy_drivers_unregister(marvell_drivers, 1064d5bf9071SChristian Hohnstaedt ARRAY_SIZE(marvell_drivers)); 106500db8189SAndy Fleming } 106600db8189SAndy Fleming 106700db8189SAndy Fleming module_init(marvell_init); 106800db8189SAndy Fleming module_exit(marvell_exit); 10694e4f10f6SDavid Woodhouse 1070cf93c945SUwe Kleine-König static struct mdio_device_id __maybe_unused marvell_tbl[] = { 1071f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1101, MARVELL_PHY_ID_MASK }, 1072f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1112, MARVELL_PHY_ID_MASK }, 1073f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1111, MARVELL_PHY_ID_MASK }, 1074f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1118, MARVELL_PHY_ID_MASK }, 1075f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1121R, MARVELL_PHY_ID_MASK }, 1076f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1145, MARVELL_PHY_ID_MASK }, 1077f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1149R, MARVELL_PHY_ID_MASK }, 1078f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1240, MARVELL_PHY_ID_MASK }, 1079f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK }, 10803da09a51SMichal Simek { MARVELL_PHY_ID_88E1116R, MARVELL_PHY_ID_MASK }, 108110e24caaSMichal Simek { MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK }, 10824e4f10f6SDavid Woodhouse { } 10834e4f10f6SDavid Woodhouse }; 10844e4f10f6SDavid Woodhouse 10854e4f10f6SDavid Woodhouse MODULE_DEVICE_TABLE(mdio, marvell_tbl); 1086