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 51239aa55bSDavid Thomson #define MII_M1011_PHY_SCR_MDI 0x0000 52239aa55bSDavid Thomson #define MII_M1011_PHY_SCR_MDI_X 0x0020 5376884679SAndy Fleming #define MII_M1011_PHY_SCR_AUTO_CROSS 0x0060 5476884679SAndy Fleming 5507151bc9SMadalin Bucur #define MII_M1145_PHY_EXT_ADDR_PAGE 0x16 56b0224175SViet Nga Dao #define MII_M1145_PHY_EXT_SR 0x1b 5776884679SAndy Fleming #define MII_M1145_PHY_EXT_CR 0x14 5876884679SAndy Fleming #define MII_M1145_RGMII_RX_DELAY 0x0080 5976884679SAndy Fleming #define MII_M1145_RGMII_TX_DELAY 0x0002 60b0224175SViet Nga Dao #define MII_M1145_HWCFG_MODE_SGMII_NO_CLK 0x4 61b0224175SViet Nga Dao #define MII_M1145_HWCFG_MODE_MASK 0xf 62b0224175SViet Nga Dao #define MII_M1145_HWCFG_FIBER_COPPER_AUTO 0x8000 6376884679SAndy Fleming 6499d881f9SVince Bridgers #define MII_M1145_HWCFG_MODE_SGMII_NO_CLK 0x4 6599d881f9SVince Bridgers #define MII_M1145_HWCFG_MODE_MASK 0xf 6699d881f9SVince Bridgers #define MII_M1145_HWCFG_FIBER_COPPER_AUTO 0x8000 6799d881f9SVince Bridgers 6876884679SAndy Fleming #define MII_M1111_PHY_LED_CONTROL 0x18 6976884679SAndy Fleming #define MII_M1111_PHY_LED_DIRECT 0x4100 7076884679SAndy Fleming #define MII_M1111_PHY_LED_COMBINE 0x411c 71895ee682SKim Phillips #define MII_M1111_PHY_EXT_CR 0x14 72895ee682SKim Phillips #define MII_M1111_RX_DELAY 0x80 73895ee682SKim Phillips #define MII_M1111_TX_DELAY 0x2 74895ee682SKim Phillips #define MII_M1111_PHY_EXT_SR 0x1b 75be937f1fSAlexandr Smirnov 76895ee682SKim Phillips #define MII_M1111_HWCFG_MODE_MASK 0xf 77be937f1fSAlexandr Smirnov #define MII_M1111_HWCFG_MODE_COPPER_RGMII 0xb 78be937f1fSAlexandr Smirnov #define MII_M1111_HWCFG_MODE_FIBER_RGMII 0x3 794117b5beSKapil Juneja #define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4 805f8cbc13SLiu Yu-B13201 #define MII_M1111_HWCFG_MODE_COPPER_RTBI 0x9 81be937f1fSAlexandr Smirnov #define MII_M1111_HWCFG_FIBER_COPPER_AUTO 0x8000 82be937f1fSAlexandr Smirnov #define MII_M1111_HWCFG_FIBER_COPPER_RES 0x2000 83be937f1fSAlexandr Smirnov 84be937f1fSAlexandr Smirnov #define MII_M1111_COPPER 0 85be937f1fSAlexandr Smirnov #define MII_M1111_FIBER 1 86be937f1fSAlexandr Smirnov 87c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_PAGE 2 88c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_REG 21 89c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_RX_DELAY BIT(5) 90c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4) 91c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4)) 92c477d044SCyril Chemparathy 93337ac9d5SCyril Chemparathy #define MII_88E1318S_PHY_MSCR1_REG 16 94337ac9d5SCyril Chemparathy #define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6) 953ff1c259SCyril Chemparathy 963871c387SMichael Stapelberg /* Copper Specific Interrupt Enable Register */ 973871c387SMichael Stapelberg #define MII_88E1318S_PHY_CSIER 0x12 983871c387SMichael Stapelberg /* WOL Event Interrupt Enable */ 993871c387SMichael Stapelberg #define MII_88E1318S_PHY_CSIER_WOL_EIE BIT(7) 1003871c387SMichael Stapelberg 1013871c387SMichael Stapelberg /* LED Timer Control Register */ 1023871c387SMichael Stapelberg #define MII_88E1318S_PHY_LED_PAGE 0x03 1033871c387SMichael Stapelberg #define MII_88E1318S_PHY_LED_TCR 0x12 1043871c387SMichael Stapelberg #define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15) 1053871c387SMichael Stapelberg #define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7) 1063871c387SMichael Stapelberg #define MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW BIT(11) 1073871c387SMichael Stapelberg 1083871c387SMichael Stapelberg /* Magic Packet MAC address registers */ 1093871c387SMichael Stapelberg #define MII_88E1318S_PHY_MAGIC_PACKET_WORD2 0x17 1103871c387SMichael Stapelberg #define MII_88E1318S_PHY_MAGIC_PACKET_WORD1 0x18 1113871c387SMichael Stapelberg #define MII_88E1318S_PHY_MAGIC_PACKET_WORD0 0x19 1123871c387SMichael Stapelberg 1133871c387SMichael Stapelberg #define MII_88E1318S_PHY_WOL_PAGE 0x11 1143871c387SMichael Stapelberg #define MII_88E1318S_PHY_WOL_CTRL 0x10 1153871c387SMichael Stapelberg #define MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS BIT(12) 1163871c387SMichael Stapelberg #define MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE BIT(14) 1173871c387SMichael Stapelberg 118140bc929SSergei Poselenov #define MII_88E1121_PHY_LED_CTRL 16 119140bc929SSergei Poselenov #define MII_88E1121_PHY_LED_PAGE 3 120140bc929SSergei Poselenov #define MII_88E1121_PHY_LED_DEF 0x0030 121140bc929SSergei Poselenov 122be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS 0x11 123be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_1000 0x8000 124be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_100 0x4000 125be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_SPD_MASK 0xc000 126be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000 127be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_RESOLVED 0x0800 128be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_LINK 0x0400 129be937f1fSAlexandr Smirnov 1303da09a51SMichal Simek #define MII_M1116R_CONTROL_REG_MAC 21 1313da09a51SMichal Simek 1326b358aedSSebastian Hesselbarth #define MII_88E3016_PHY_SPEC_CTRL 0x10 1336b358aedSSebastian Hesselbarth #define MII_88E3016_DISABLE_SCRAMBLER 0x0200 1346b358aedSSebastian Hesselbarth #define MII_88E3016_AUTO_MDIX_CROSSOVER 0x0030 13576884679SAndy Fleming 136930b37eeSStefan Roese #define MII_88E1510_GEN_CTRL_REG_1 0x14 137930b37eeSStefan Roese #define MII_88E1510_GEN_CTRL_REG_1_MODE_MASK 0x7 138930b37eeSStefan Roese #define MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII 0x1 /* SGMII to copper */ 139930b37eeSStefan Roese #define MII_88E1510_GEN_CTRL_REG_1_RESET 0x8000 /* Soft reset */ 140930b37eeSStefan Roese 14100db8189SAndy Fleming MODULE_DESCRIPTION("Marvell PHY driver"); 14200db8189SAndy Fleming MODULE_AUTHOR("Andy Fleming"); 14300db8189SAndy Fleming MODULE_LICENSE("GPL"); 14400db8189SAndy Fleming 145d2fa47d9SAndrew Lunn struct marvell_hw_stat { 146d2fa47d9SAndrew Lunn const char *string; 147d2fa47d9SAndrew Lunn u8 page; 148d2fa47d9SAndrew Lunn u8 reg; 149d2fa47d9SAndrew Lunn u8 bits; 150d2fa47d9SAndrew Lunn }; 151d2fa47d9SAndrew Lunn 152d2fa47d9SAndrew Lunn static struct marvell_hw_stat marvell_hw_stats[] = { 153d2fa47d9SAndrew Lunn { "phy_receive_errors", 0, 21, 16}, 154d2fa47d9SAndrew Lunn { "phy_idle_errors", 0, 10, 8 }, 155d2fa47d9SAndrew Lunn }; 156d2fa47d9SAndrew Lunn 157d2fa47d9SAndrew Lunn struct marvell_priv { 158d2fa47d9SAndrew Lunn u64 stats[ARRAY_SIZE(marvell_hw_stats)]; 159d2fa47d9SAndrew Lunn }; 160d2fa47d9SAndrew Lunn 16100db8189SAndy Fleming static int marvell_ack_interrupt(struct phy_device *phydev) 16200db8189SAndy Fleming { 16300db8189SAndy Fleming int err; 16400db8189SAndy Fleming 16500db8189SAndy Fleming /* Clear the interrupts by reading the reg */ 16600db8189SAndy Fleming err = phy_read(phydev, MII_M1011_IEVENT); 16700db8189SAndy Fleming 16800db8189SAndy Fleming if (err < 0) 16900db8189SAndy Fleming return err; 17000db8189SAndy Fleming 17100db8189SAndy Fleming return 0; 17200db8189SAndy Fleming } 17300db8189SAndy Fleming 17400db8189SAndy Fleming static int marvell_config_intr(struct phy_device *phydev) 17500db8189SAndy Fleming { 17600db8189SAndy Fleming int err; 17700db8189SAndy Fleming 17800db8189SAndy Fleming if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 17900db8189SAndy Fleming err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT); 18000db8189SAndy Fleming else 18100db8189SAndy Fleming err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); 18200db8189SAndy Fleming 18300db8189SAndy Fleming return err; 18400db8189SAndy Fleming } 18500db8189SAndy Fleming 186239aa55bSDavid Thomson static int marvell_set_polarity(struct phy_device *phydev, int polarity) 187239aa55bSDavid Thomson { 188239aa55bSDavid Thomson int reg; 189239aa55bSDavid Thomson int err; 190239aa55bSDavid Thomson int val; 191239aa55bSDavid Thomson 192239aa55bSDavid Thomson /* get the current settings */ 193239aa55bSDavid Thomson reg = phy_read(phydev, MII_M1011_PHY_SCR); 194239aa55bSDavid Thomson if (reg < 0) 195239aa55bSDavid Thomson return reg; 196239aa55bSDavid Thomson 197239aa55bSDavid Thomson val = reg; 198239aa55bSDavid Thomson val &= ~MII_M1011_PHY_SCR_AUTO_CROSS; 199239aa55bSDavid Thomson switch (polarity) { 200239aa55bSDavid Thomson case ETH_TP_MDI: 201239aa55bSDavid Thomson val |= MII_M1011_PHY_SCR_MDI; 202239aa55bSDavid Thomson break; 203239aa55bSDavid Thomson case ETH_TP_MDI_X: 204239aa55bSDavid Thomson val |= MII_M1011_PHY_SCR_MDI_X; 205239aa55bSDavid Thomson break; 206239aa55bSDavid Thomson case ETH_TP_MDI_AUTO: 207239aa55bSDavid Thomson case ETH_TP_MDI_INVALID: 208239aa55bSDavid Thomson default: 209239aa55bSDavid Thomson val |= MII_M1011_PHY_SCR_AUTO_CROSS; 210239aa55bSDavid Thomson break; 211239aa55bSDavid Thomson } 212239aa55bSDavid Thomson 213239aa55bSDavid Thomson if (val != reg) { 214239aa55bSDavid Thomson /* Set the new polarity value in the register */ 215239aa55bSDavid Thomson err = phy_write(phydev, MII_M1011_PHY_SCR, val); 216239aa55bSDavid Thomson if (err) 217239aa55bSDavid Thomson return err; 218239aa55bSDavid Thomson } 219239aa55bSDavid Thomson 220239aa55bSDavid Thomson return 0; 221239aa55bSDavid Thomson } 222239aa55bSDavid Thomson 22300db8189SAndy Fleming static int marvell_config_aneg(struct phy_device *phydev) 22400db8189SAndy Fleming { 22500db8189SAndy Fleming int err; 22600db8189SAndy Fleming 22700db8189SAndy Fleming /* The Marvell PHY has an errata which requires 22800db8189SAndy Fleming * that certain registers get written in order 22900db8189SAndy Fleming * to restart autonegotiation */ 23000db8189SAndy Fleming err = phy_write(phydev, MII_BMCR, BMCR_RESET); 23100db8189SAndy Fleming 23200db8189SAndy Fleming if (err < 0) 23300db8189SAndy Fleming return err; 23400db8189SAndy Fleming 23500db8189SAndy Fleming err = phy_write(phydev, 0x1d, 0x1f); 23600db8189SAndy Fleming if (err < 0) 23700db8189SAndy Fleming return err; 23800db8189SAndy Fleming 23900db8189SAndy Fleming err = phy_write(phydev, 0x1e, 0x200c); 24000db8189SAndy Fleming if (err < 0) 24100db8189SAndy Fleming return err; 24200db8189SAndy Fleming 24300db8189SAndy Fleming err = phy_write(phydev, 0x1d, 0x5); 24400db8189SAndy Fleming if (err < 0) 24500db8189SAndy Fleming return err; 24600db8189SAndy Fleming 24700db8189SAndy Fleming err = phy_write(phydev, 0x1e, 0); 24800db8189SAndy Fleming if (err < 0) 24900db8189SAndy Fleming return err; 25000db8189SAndy Fleming 25100db8189SAndy Fleming err = phy_write(phydev, 0x1e, 0x100); 25200db8189SAndy Fleming if (err < 0) 25300db8189SAndy Fleming return err; 25400db8189SAndy Fleming 255239aa55bSDavid Thomson err = marvell_set_polarity(phydev, phydev->mdix); 25676884679SAndy Fleming if (err < 0) 25776884679SAndy Fleming return err; 25876884679SAndy Fleming 25976884679SAndy Fleming err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL, 26076884679SAndy Fleming MII_M1111_PHY_LED_DIRECT); 26176884679SAndy Fleming if (err < 0) 26276884679SAndy Fleming return err; 26300db8189SAndy Fleming 26400db8189SAndy Fleming err = genphy_config_aneg(phydev); 2658ff44985SAnton Vorontsov if (err < 0) 26600db8189SAndy Fleming return err; 2678ff44985SAnton Vorontsov 2688ff44985SAnton Vorontsov if (phydev->autoneg != AUTONEG_ENABLE) { 2698ff44985SAnton Vorontsov int bmcr; 2708ff44985SAnton Vorontsov 2718ff44985SAnton Vorontsov /* 2728ff44985SAnton Vorontsov * A write to speed/duplex bits (that is performed by 2738ff44985SAnton Vorontsov * genphy_config_aneg() call above) must be followed by 2748ff44985SAnton Vorontsov * a software reset. Otherwise, the write has no effect. 2758ff44985SAnton Vorontsov */ 2768ff44985SAnton Vorontsov bmcr = phy_read(phydev, MII_BMCR); 2778ff44985SAnton Vorontsov if (bmcr < 0) 2788ff44985SAnton Vorontsov return bmcr; 2798ff44985SAnton Vorontsov 2808ff44985SAnton Vorontsov err = phy_write(phydev, MII_BMCR, bmcr | BMCR_RESET); 2818ff44985SAnton Vorontsov if (err < 0) 2828ff44985SAnton Vorontsov return err; 2838ff44985SAnton Vorontsov } 2848ff44985SAnton Vorontsov 2858ff44985SAnton Vorontsov return 0; 28600db8189SAndy Fleming } 28700db8189SAndy Fleming 2883ec0a0f1SHarini Katakam static int m88e1111_config_aneg(struct phy_device *phydev) 2893ec0a0f1SHarini Katakam { 2903ec0a0f1SHarini Katakam int err; 2913ec0a0f1SHarini Katakam 2923ec0a0f1SHarini Katakam /* The Marvell PHY has an errata which requires 2933ec0a0f1SHarini Katakam * that certain registers get written in order 2943ec0a0f1SHarini Katakam * to restart autonegotiation 2953ec0a0f1SHarini Katakam */ 2963ec0a0f1SHarini Katakam err = phy_write(phydev, MII_BMCR, BMCR_RESET); 2973ec0a0f1SHarini Katakam 2983ec0a0f1SHarini Katakam err = marvell_set_polarity(phydev, phydev->mdix); 2993ec0a0f1SHarini Katakam if (err < 0) 3003ec0a0f1SHarini Katakam return err; 3013ec0a0f1SHarini Katakam 3023ec0a0f1SHarini Katakam err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL, 3033ec0a0f1SHarini Katakam MII_M1111_PHY_LED_DIRECT); 3043ec0a0f1SHarini Katakam if (err < 0) 3053ec0a0f1SHarini Katakam return err; 3063ec0a0f1SHarini Katakam 3073ec0a0f1SHarini Katakam err = genphy_config_aneg(phydev); 3083ec0a0f1SHarini Katakam if (err < 0) 3093ec0a0f1SHarini Katakam return err; 3103ec0a0f1SHarini Katakam 3113ec0a0f1SHarini Katakam if (phydev->autoneg != AUTONEG_ENABLE) { 3123ec0a0f1SHarini Katakam int bmcr; 3133ec0a0f1SHarini Katakam 3143ec0a0f1SHarini Katakam /* A write to speed/duplex bits (that is performed by 3153ec0a0f1SHarini Katakam * genphy_config_aneg() call above) must be followed by 3163ec0a0f1SHarini Katakam * a software reset. Otherwise, the write has no effect. 3173ec0a0f1SHarini Katakam */ 3183ec0a0f1SHarini Katakam bmcr = phy_read(phydev, MII_BMCR); 3193ec0a0f1SHarini Katakam if (bmcr < 0) 3203ec0a0f1SHarini Katakam return bmcr; 3213ec0a0f1SHarini Katakam 3223ec0a0f1SHarini Katakam err = phy_write(phydev, MII_BMCR, bmcr | BMCR_RESET); 3233ec0a0f1SHarini Katakam if (err < 0) 3243ec0a0f1SHarini Katakam return err; 3253ec0a0f1SHarini Katakam } 3263ec0a0f1SHarini Katakam 3273ec0a0f1SHarini Katakam return 0; 3283ec0a0f1SHarini Katakam } 3293ec0a0f1SHarini Katakam 330cf41a51dSDavid Daney #ifdef CONFIG_OF_MDIO 331cf41a51dSDavid Daney /* 332cf41a51dSDavid Daney * Set and/or override some configuration registers based on the 333cf41a51dSDavid Daney * marvell,reg-init property stored in the of_node for the phydev. 334cf41a51dSDavid Daney * 335cf41a51dSDavid Daney * marvell,reg-init = <reg-page reg mask value>,...; 336cf41a51dSDavid Daney * 337cf41a51dSDavid Daney * There may be one or more sets of <reg-page reg mask value>: 338cf41a51dSDavid Daney * 339cf41a51dSDavid Daney * reg-page: which register bank to use. 340cf41a51dSDavid Daney * reg: the register. 341cf41a51dSDavid Daney * mask: if non-zero, ANDed with existing register value. 342cf41a51dSDavid Daney * value: ORed with the masked value and written to the regiser. 343cf41a51dSDavid Daney * 344cf41a51dSDavid Daney */ 345cf41a51dSDavid Daney static int marvell_of_reg_init(struct phy_device *phydev) 346cf41a51dSDavid Daney { 347cf41a51dSDavid Daney const __be32 *paddr; 348cf41a51dSDavid Daney int len, i, saved_page, current_page, page_changed, ret; 349cf41a51dSDavid Daney 350e5a03bfdSAndrew Lunn if (!phydev->mdio.dev.of_node) 351cf41a51dSDavid Daney return 0; 352cf41a51dSDavid Daney 353e5a03bfdSAndrew Lunn paddr = of_get_property(phydev->mdio.dev.of_node, 354e5a03bfdSAndrew Lunn "marvell,reg-init", &len); 355cf41a51dSDavid Daney if (!paddr || len < (4 * sizeof(*paddr))) 356cf41a51dSDavid Daney return 0; 357cf41a51dSDavid Daney 358cf41a51dSDavid Daney saved_page = phy_read(phydev, MII_MARVELL_PHY_PAGE); 359cf41a51dSDavid Daney if (saved_page < 0) 360cf41a51dSDavid Daney return saved_page; 361cf41a51dSDavid Daney page_changed = 0; 362cf41a51dSDavid Daney current_page = saved_page; 363cf41a51dSDavid Daney 364cf41a51dSDavid Daney ret = 0; 365cf41a51dSDavid Daney len /= sizeof(*paddr); 366cf41a51dSDavid Daney for (i = 0; i < len - 3; i += 4) { 367cf41a51dSDavid Daney u16 reg_page = be32_to_cpup(paddr + i); 368cf41a51dSDavid Daney u16 reg = be32_to_cpup(paddr + i + 1); 369cf41a51dSDavid Daney u16 mask = be32_to_cpup(paddr + i + 2); 370cf41a51dSDavid Daney u16 val_bits = be32_to_cpup(paddr + i + 3); 371cf41a51dSDavid Daney int val; 372cf41a51dSDavid Daney 373cf41a51dSDavid Daney if (reg_page != current_page) { 374cf41a51dSDavid Daney current_page = reg_page; 375cf41a51dSDavid Daney page_changed = 1; 376cf41a51dSDavid Daney ret = phy_write(phydev, MII_MARVELL_PHY_PAGE, reg_page); 377cf41a51dSDavid Daney if (ret < 0) 378cf41a51dSDavid Daney goto err; 379cf41a51dSDavid Daney } 380cf41a51dSDavid Daney 381cf41a51dSDavid Daney val = 0; 382cf41a51dSDavid Daney if (mask) { 383cf41a51dSDavid Daney val = phy_read(phydev, reg); 384cf41a51dSDavid Daney if (val < 0) { 385cf41a51dSDavid Daney ret = val; 386cf41a51dSDavid Daney goto err; 387cf41a51dSDavid Daney } 388cf41a51dSDavid Daney val &= mask; 389cf41a51dSDavid Daney } 390cf41a51dSDavid Daney val |= val_bits; 391cf41a51dSDavid Daney 392cf41a51dSDavid Daney ret = phy_write(phydev, reg, val); 393cf41a51dSDavid Daney if (ret < 0) 394cf41a51dSDavid Daney goto err; 395cf41a51dSDavid Daney 396cf41a51dSDavid Daney } 397cf41a51dSDavid Daney err: 398cf41a51dSDavid Daney if (page_changed) { 399cf41a51dSDavid Daney i = phy_write(phydev, MII_MARVELL_PHY_PAGE, saved_page); 400cf41a51dSDavid Daney if (ret == 0) 401cf41a51dSDavid Daney ret = i; 402cf41a51dSDavid Daney } 403cf41a51dSDavid Daney return ret; 404cf41a51dSDavid Daney } 405cf41a51dSDavid Daney #else 406cf41a51dSDavid Daney static int marvell_of_reg_init(struct phy_device *phydev) 407cf41a51dSDavid Daney { 408cf41a51dSDavid Daney return 0; 409cf41a51dSDavid Daney } 410cf41a51dSDavid Daney #endif /* CONFIG_OF_MDIO */ 411cf41a51dSDavid Daney 412140bc929SSergei Poselenov static int m88e1121_config_aneg(struct phy_device *phydev) 413140bc929SSergei Poselenov { 414c477d044SCyril Chemparathy int err, oldpage, mscr; 415c477d044SCyril Chemparathy 41627d916d6SDavid Daney oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); 417c477d044SCyril Chemparathy 41827d916d6SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 419c477d044SCyril Chemparathy MII_88E1121_PHY_MSCR_PAGE); 420c477d044SCyril Chemparathy if (err < 0) 421c477d044SCyril Chemparathy return err; 422be8c6480SArnaud Patard 42332a64161SFlorian Fainelli if (phy_interface_is_rgmii(phydev)) { 424be8c6480SArnaud Patard 425c477d044SCyril Chemparathy mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) & 426c477d044SCyril Chemparathy MII_88E1121_PHY_MSCR_DELAY_MASK; 427c477d044SCyril Chemparathy 428c477d044SCyril Chemparathy if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 429c477d044SCyril Chemparathy mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY | 430c477d044SCyril Chemparathy MII_88E1121_PHY_MSCR_TX_DELAY); 431c477d044SCyril Chemparathy else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) 432c477d044SCyril Chemparathy mscr |= MII_88E1121_PHY_MSCR_RX_DELAY; 433c477d044SCyril Chemparathy else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) 434c477d044SCyril Chemparathy mscr |= MII_88E1121_PHY_MSCR_TX_DELAY; 435c477d044SCyril Chemparathy 436c477d044SCyril Chemparathy err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr); 437c477d044SCyril Chemparathy if (err < 0) 438c477d044SCyril Chemparathy return err; 439be8c6480SArnaud Patard } 440c477d044SCyril Chemparathy 44127d916d6SDavid Daney phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage); 442140bc929SSergei Poselenov 443140bc929SSergei Poselenov err = phy_write(phydev, MII_BMCR, BMCR_RESET); 444140bc929SSergei Poselenov if (err < 0) 445140bc929SSergei Poselenov return err; 446140bc929SSergei Poselenov 447140bc929SSergei Poselenov err = phy_write(phydev, MII_M1011_PHY_SCR, 448140bc929SSergei Poselenov MII_M1011_PHY_SCR_AUTO_CROSS); 449140bc929SSergei Poselenov if (err < 0) 450140bc929SSergei Poselenov return err; 451140bc929SSergei Poselenov 452fdecf36fSClemens Gruber return genphy_config_aneg(phydev); 453140bc929SSergei Poselenov } 454140bc929SSergei Poselenov 455337ac9d5SCyril Chemparathy static int m88e1318_config_aneg(struct phy_device *phydev) 4563ff1c259SCyril Chemparathy { 4573ff1c259SCyril Chemparathy int err, oldpage, mscr; 4583ff1c259SCyril Chemparathy 45927d916d6SDavid Daney oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); 4603ff1c259SCyril Chemparathy 46127d916d6SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 4623ff1c259SCyril Chemparathy MII_88E1121_PHY_MSCR_PAGE); 4633ff1c259SCyril Chemparathy if (err < 0) 4643ff1c259SCyril Chemparathy return err; 4653ff1c259SCyril Chemparathy 466337ac9d5SCyril Chemparathy mscr = phy_read(phydev, MII_88E1318S_PHY_MSCR1_REG); 467337ac9d5SCyril Chemparathy mscr |= MII_88E1318S_PHY_MSCR1_PAD_ODD; 4683ff1c259SCyril Chemparathy 469337ac9d5SCyril Chemparathy err = phy_write(phydev, MII_88E1318S_PHY_MSCR1_REG, mscr); 4703ff1c259SCyril Chemparathy if (err < 0) 4713ff1c259SCyril Chemparathy return err; 4723ff1c259SCyril Chemparathy 47327d916d6SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage); 4743ff1c259SCyril Chemparathy if (err < 0) 4753ff1c259SCyril Chemparathy return err; 4763ff1c259SCyril Chemparathy 4773ff1c259SCyril Chemparathy return m88e1121_config_aneg(phydev); 4783ff1c259SCyril Chemparathy } 4793ff1c259SCyril Chemparathy 48010e24caaSMichal Simek static int m88e1510_config_aneg(struct phy_device *phydev) 48110e24caaSMichal Simek { 48210e24caaSMichal Simek int err; 48310e24caaSMichal Simek 48410e24caaSMichal Simek err = m88e1318_config_aneg(phydev); 48510e24caaSMichal Simek if (err < 0) 48610e24caaSMichal Simek return err; 48710e24caaSMichal Simek 48879be1a1cSClemens Gruber return 0; 48979be1a1cSClemens Gruber } 49079be1a1cSClemens Gruber 49179be1a1cSClemens Gruber static int marvell_config_init(struct phy_device *phydev) 49279be1a1cSClemens Gruber { 49379be1a1cSClemens Gruber /* Set registers from marvell,reg-init DT property */ 49410e24caaSMichal Simek return marvell_of_reg_init(phydev); 49510e24caaSMichal Simek } 49610e24caaSMichal Simek 4973da09a51SMichal Simek static int m88e1116r_config_init(struct phy_device *phydev) 4983da09a51SMichal Simek { 4993da09a51SMichal Simek int temp; 5003da09a51SMichal Simek int err; 5013da09a51SMichal Simek 5023da09a51SMichal Simek temp = phy_read(phydev, MII_BMCR); 5033da09a51SMichal Simek temp |= BMCR_RESET; 5043da09a51SMichal Simek err = phy_write(phydev, MII_BMCR, temp); 5053da09a51SMichal Simek if (err < 0) 5063da09a51SMichal Simek return err; 5073da09a51SMichal Simek 5083da09a51SMichal Simek mdelay(500); 5093da09a51SMichal Simek 5103da09a51SMichal Simek err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0); 5113da09a51SMichal Simek if (err < 0) 5123da09a51SMichal Simek return err; 5133da09a51SMichal Simek 5143da09a51SMichal Simek temp = phy_read(phydev, MII_M1011_PHY_SCR); 5153da09a51SMichal Simek temp |= (7 << 12); /* max number of gigabit attempts */ 5163da09a51SMichal Simek temp |= (1 << 11); /* enable downshift */ 5173da09a51SMichal Simek temp |= MII_M1011_PHY_SCR_AUTO_CROSS; 5183da09a51SMichal Simek err = phy_write(phydev, MII_M1011_PHY_SCR, temp); 5193da09a51SMichal Simek if (err < 0) 5203da09a51SMichal Simek return err; 5213da09a51SMichal Simek 5223da09a51SMichal Simek err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 2); 5233da09a51SMichal Simek if (err < 0) 5243da09a51SMichal Simek return err; 5253da09a51SMichal Simek temp = phy_read(phydev, MII_M1116R_CONTROL_REG_MAC); 5263da09a51SMichal Simek temp |= (1 << 5); 5273da09a51SMichal Simek temp |= (1 << 4); 5283da09a51SMichal Simek err = phy_write(phydev, MII_M1116R_CONTROL_REG_MAC, temp); 5293da09a51SMichal Simek if (err < 0) 5303da09a51SMichal Simek return err; 5313da09a51SMichal Simek err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0); 5323da09a51SMichal Simek if (err < 0) 5333da09a51SMichal Simek return err; 5343da09a51SMichal Simek 5353da09a51SMichal Simek temp = phy_read(phydev, MII_BMCR); 5363da09a51SMichal Simek temp |= BMCR_RESET; 5373da09a51SMichal Simek err = phy_write(phydev, MII_BMCR, temp); 5383da09a51SMichal Simek if (err < 0) 5393da09a51SMichal Simek return err; 5403da09a51SMichal Simek 5413da09a51SMichal Simek mdelay(500); 5423da09a51SMichal Simek 54379be1a1cSClemens Gruber return marvell_config_init(phydev); 5443da09a51SMichal Simek } 5453da09a51SMichal Simek 5466b358aedSSebastian Hesselbarth static int m88e3016_config_init(struct phy_device *phydev) 5476b358aedSSebastian Hesselbarth { 5486b358aedSSebastian Hesselbarth int reg; 5496b358aedSSebastian Hesselbarth 5506b358aedSSebastian Hesselbarth /* Enable Scrambler and Auto-Crossover */ 5516b358aedSSebastian Hesselbarth reg = phy_read(phydev, MII_88E3016_PHY_SPEC_CTRL); 5526b358aedSSebastian Hesselbarth if (reg < 0) 5536b358aedSSebastian Hesselbarth return reg; 5546b358aedSSebastian Hesselbarth 5556b358aedSSebastian Hesselbarth reg &= ~MII_88E3016_DISABLE_SCRAMBLER; 5566b358aedSSebastian Hesselbarth reg |= MII_88E3016_AUTO_MDIX_CROSSOVER; 5576b358aedSSebastian Hesselbarth 5586b358aedSSebastian Hesselbarth reg = phy_write(phydev, MII_88E3016_PHY_SPEC_CTRL, reg); 5596b358aedSSebastian Hesselbarth if (reg < 0) 5606b358aedSSebastian Hesselbarth return reg; 5616b358aedSSebastian Hesselbarth 56279be1a1cSClemens Gruber return marvell_config_init(phydev); 5636b358aedSSebastian Hesselbarth } 5646b358aedSSebastian Hesselbarth 565895ee682SKim Phillips static int m88e1111_config_init(struct phy_device *phydev) 566895ee682SKim Phillips { 567895ee682SKim Phillips int err; 568be937f1fSAlexandr Smirnov int temp; 569be937f1fSAlexandr Smirnov 57032a64161SFlorian Fainelli if (phy_interface_is_rgmii(phydev)) { 571895ee682SKim Phillips 572895ee682SKim Phillips temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); 573895ee682SKim Phillips if (temp < 0) 574895ee682SKim Phillips return temp; 575895ee682SKim Phillips 5769daf5a76SKim Phillips if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { 577895ee682SKim Phillips temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); 5789daf5a76SKim Phillips } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 5799daf5a76SKim Phillips temp &= ~MII_M1111_TX_DELAY; 5809daf5a76SKim Phillips temp |= MII_M1111_RX_DELAY; 5819daf5a76SKim Phillips } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 5829daf5a76SKim Phillips temp &= ~MII_M1111_RX_DELAY; 5839daf5a76SKim Phillips temp |= MII_M1111_TX_DELAY; 5849daf5a76SKim Phillips } 585895ee682SKim Phillips 586895ee682SKim Phillips err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); 587895ee682SKim Phillips if (err < 0) 588895ee682SKim Phillips return err; 589895ee682SKim Phillips 590895ee682SKim Phillips temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 591895ee682SKim Phillips if (temp < 0) 592895ee682SKim Phillips return temp; 593895ee682SKim Phillips 594895ee682SKim Phillips temp &= ~(MII_M1111_HWCFG_MODE_MASK); 595be937f1fSAlexandr Smirnov 5967239016dSWang Jian if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES) 597be937f1fSAlexandr Smirnov temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII; 598be937f1fSAlexandr Smirnov else 599be937f1fSAlexandr Smirnov temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII; 600895ee682SKim Phillips 601895ee682SKim Phillips err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 602895ee682SKim Phillips if (err < 0) 603895ee682SKim Phillips return err; 604895ee682SKim Phillips } 605895ee682SKim Phillips 6064117b5beSKapil Juneja if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { 6074117b5beSKapil Juneja temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 6084117b5beSKapil Juneja if (temp < 0) 6094117b5beSKapil Juneja return temp; 6104117b5beSKapil Juneja 6114117b5beSKapil Juneja temp &= ~(MII_M1111_HWCFG_MODE_MASK); 6124117b5beSKapil Juneja temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK; 61332d0c1e1SHaiying Wang temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO; 6144117b5beSKapil Juneja 6154117b5beSKapil Juneja err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 6164117b5beSKapil Juneja if (err < 0) 6174117b5beSKapil Juneja return err; 61807151bc9SMadalin Bucur 61907151bc9SMadalin Bucur /* make sure copper is selected */ 62007151bc9SMadalin Bucur err = phy_read(phydev, MII_M1145_PHY_EXT_ADDR_PAGE); 62107151bc9SMadalin Bucur if (err < 0) 62207151bc9SMadalin Bucur return err; 62307151bc9SMadalin Bucur 62407151bc9SMadalin Bucur err = phy_write(phydev, MII_M1145_PHY_EXT_ADDR_PAGE, 62507151bc9SMadalin Bucur err & (~0xff)); 62607151bc9SMadalin Bucur if (err < 0) 62707151bc9SMadalin Bucur return err; 6284117b5beSKapil Juneja } 6294117b5beSKapil Juneja 6305f8cbc13SLiu Yu-B13201 if (phydev->interface == PHY_INTERFACE_MODE_RTBI) { 6315f8cbc13SLiu Yu-B13201 temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); 6325f8cbc13SLiu Yu-B13201 if (temp < 0) 6335f8cbc13SLiu Yu-B13201 return temp; 6345f8cbc13SLiu Yu-B13201 temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); 6355f8cbc13SLiu Yu-B13201 err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); 6365f8cbc13SLiu Yu-B13201 if (err < 0) 6375f8cbc13SLiu Yu-B13201 return err; 6385f8cbc13SLiu Yu-B13201 6395f8cbc13SLiu Yu-B13201 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 6405f8cbc13SLiu Yu-B13201 if (temp < 0) 6415f8cbc13SLiu Yu-B13201 return temp; 6425f8cbc13SLiu Yu-B13201 temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES); 6435f8cbc13SLiu Yu-B13201 temp |= 0x7 | MII_M1111_HWCFG_FIBER_COPPER_AUTO; 6445f8cbc13SLiu Yu-B13201 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 6455f8cbc13SLiu Yu-B13201 if (err < 0) 6465f8cbc13SLiu Yu-B13201 return err; 6475f8cbc13SLiu Yu-B13201 6485f8cbc13SLiu Yu-B13201 /* soft reset */ 6495f8cbc13SLiu Yu-B13201 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 6505f8cbc13SLiu Yu-B13201 if (err < 0) 6515f8cbc13SLiu Yu-B13201 return err; 6525f8cbc13SLiu Yu-B13201 do 6535f8cbc13SLiu Yu-B13201 temp = phy_read(phydev, MII_BMCR); 6545f8cbc13SLiu Yu-B13201 while (temp & BMCR_RESET); 6555f8cbc13SLiu Yu-B13201 6565f8cbc13SLiu Yu-B13201 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 6575f8cbc13SLiu Yu-B13201 if (temp < 0) 6585f8cbc13SLiu Yu-B13201 return temp; 6595f8cbc13SLiu Yu-B13201 temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES); 6605f8cbc13SLiu Yu-B13201 temp |= MII_M1111_HWCFG_MODE_COPPER_RTBI | MII_M1111_HWCFG_FIBER_COPPER_AUTO; 6615f8cbc13SLiu Yu-B13201 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 6625f8cbc13SLiu Yu-B13201 if (err < 0) 6635f8cbc13SLiu Yu-B13201 return err; 6645f8cbc13SLiu Yu-B13201 } 6655f8cbc13SLiu Yu-B13201 666cf41a51dSDavid Daney err = marvell_of_reg_init(phydev); 667cf41a51dSDavid Daney if (err < 0) 668cf41a51dSDavid Daney return err; 6695f8cbc13SLiu Yu-B13201 670cc90cb3bSSrinivas Kandagatla return phy_write(phydev, MII_BMCR, BMCR_RESET); 671895ee682SKim Phillips } 672895ee682SKim Phillips 673fdecf36fSClemens Gruber static int m88e1121_config_init(struct phy_device *phydev) 674fdecf36fSClemens Gruber { 675fdecf36fSClemens Gruber int err, oldpage; 676fdecf36fSClemens Gruber 677fdecf36fSClemens Gruber oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); 678fdecf36fSClemens Gruber 679fdecf36fSClemens Gruber err = phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_88E1121_PHY_LED_PAGE); 680fdecf36fSClemens Gruber if (err < 0) 681fdecf36fSClemens Gruber return err; 682fdecf36fSClemens Gruber 683fdecf36fSClemens Gruber /* Default PHY LED config: LED[0] .. Link, LED[1] .. Activity */ 684fdecf36fSClemens Gruber err = phy_write(phydev, MII_88E1121_PHY_LED_CTRL, 685fdecf36fSClemens Gruber MII_88E1121_PHY_LED_DEF); 686fdecf36fSClemens Gruber if (err < 0) 687fdecf36fSClemens Gruber return err; 688fdecf36fSClemens Gruber 689fdecf36fSClemens Gruber phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage); 690fdecf36fSClemens Gruber 691fdecf36fSClemens Gruber /* Set marvell,reg-init configuration from device tree */ 692fdecf36fSClemens Gruber return marvell_config_init(phydev); 693fdecf36fSClemens Gruber } 694fdecf36fSClemens Gruber 695407353ecSClemens Gruber static int m88e1510_config_init(struct phy_device *phydev) 696407353ecSClemens Gruber { 697407353ecSClemens Gruber int err; 698407353ecSClemens Gruber int temp; 699407353ecSClemens Gruber 700407353ecSClemens Gruber /* SGMII-to-Copper mode initialization */ 701407353ecSClemens Gruber if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { 702407353ecSClemens Gruber /* Select page 18 */ 703407353ecSClemens Gruber err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 18); 704407353ecSClemens Gruber if (err < 0) 705407353ecSClemens Gruber return err; 706407353ecSClemens Gruber 707407353ecSClemens Gruber /* In reg 20, write MODE[2:0] = 0x1 (SGMII to Copper) */ 708407353ecSClemens Gruber temp = phy_read(phydev, MII_88E1510_GEN_CTRL_REG_1); 709407353ecSClemens Gruber temp &= ~MII_88E1510_GEN_CTRL_REG_1_MODE_MASK; 710407353ecSClemens Gruber temp |= MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII; 711407353ecSClemens Gruber err = phy_write(phydev, MII_88E1510_GEN_CTRL_REG_1, temp); 712407353ecSClemens Gruber if (err < 0) 713407353ecSClemens Gruber return err; 714407353ecSClemens Gruber 715407353ecSClemens Gruber /* PHY reset is necessary after changing MODE[2:0] */ 716407353ecSClemens Gruber temp |= MII_88E1510_GEN_CTRL_REG_1_RESET; 717407353ecSClemens Gruber err = phy_write(phydev, MII_88E1510_GEN_CTRL_REG_1, temp); 718407353ecSClemens Gruber if (err < 0) 719407353ecSClemens Gruber return err; 720407353ecSClemens Gruber 721407353ecSClemens Gruber /* Reset page selection */ 722407353ecSClemens Gruber err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0); 723407353ecSClemens Gruber if (err < 0) 724407353ecSClemens Gruber return err; 725407353ecSClemens Gruber } 726407353ecSClemens Gruber 727fdecf36fSClemens Gruber return m88e1121_config_init(phydev); 728407353ecSClemens Gruber } 729407353ecSClemens Gruber 730605f196eSRon Madrid static int m88e1118_config_aneg(struct phy_device *phydev) 731605f196eSRon Madrid { 732605f196eSRon Madrid int err; 733605f196eSRon Madrid 734605f196eSRon Madrid err = phy_write(phydev, MII_BMCR, BMCR_RESET); 735605f196eSRon Madrid if (err < 0) 736605f196eSRon Madrid return err; 737605f196eSRon Madrid 738605f196eSRon Madrid err = phy_write(phydev, MII_M1011_PHY_SCR, 739605f196eSRon Madrid MII_M1011_PHY_SCR_AUTO_CROSS); 740605f196eSRon Madrid if (err < 0) 741605f196eSRon Madrid return err; 742605f196eSRon Madrid 743605f196eSRon Madrid err = genphy_config_aneg(phydev); 744605f196eSRon Madrid return 0; 745605f196eSRon Madrid } 746605f196eSRon Madrid 747605f196eSRon Madrid static int m88e1118_config_init(struct phy_device *phydev) 748605f196eSRon Madrid { 749605f196eSRon Madrid int err; 750605f196eSRon Madrid 751605f196eSRon Madrid /* Change address */ 75227d916d6SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0002); 753605f196eSRon Madrid if (err < 0) 754605f196eSRon Madrid return err; 755605f196eSRon Madrid 756605f196eSRon Madrid /* Enable 1000 Mbit */ 757605f196eSRon Madrid err = phy_write(phydev, 0x15, 0x1070); 758605f196eSRon Madrid if (err < 0) 759605f196eSRon Madrid return err; 760605f196eSRon Madrid 761605f196eSRon Madrid /* Change address */ 76227d916d6SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0003); 763605f196eSRon Madrid if (err < 0) 764605f196eSRon Madrid return err; 765605f196eSRon Madrid 766605f196eSRon Madrid /* Adjust LED Control */ 7672f495c39SBenjamin Herrenschmidt if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS) 7682f495c39SBenjamin Herrenschmidt err = phy_write(phydev, 0x10, 0x1100); 7692f495c39SBenjamin Herrenschmidt else 770605f196eSRon Madrid err = phy_write(phydev, 0x10, 0x021e); 771605f196eSRon Madrid if (err < 0) 772605f196eSRon Madrid return err; 773605f196eSRon Madrid 774cf41a51dSDavid Daney err = marvell_of_reg_init(phydev); 775cf41a51dSDavid Daney if (err < 0) 776cf41a51dSDavid Daney return err; 777cf41a51dSDavid Daney 778605f196eSRon Madrid /* Reset address */ 77927d916d6SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0); 780605f196eSRon Madrid if (err < 0) 781605f196eSRon Madrid return err; 782605f196eSRon Madrid 783cc90cb3bSSrinivas Kandagatla return phy_write(phydev, MII_BMCR, BMCR_RESET); 784605f196eSRon Madrid } 785605f196eSRon Madrid 78690600732SDavid Daney static int m88e1149_config_init(struct phy_device *phydev) 78790600732SDavid Daney { 78890600732SDavid Daney int err; 78990600732SDavid Daney 79090600732SDavid Daney /* Change address */ 79190600732SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0002); 79290600732SDavid Daney if (err < 0) 79390600732SDavid Daney return err; 79490600732SDavid Daney 79590600732SDavid Daney /* Enable 1000 Mbit */ 79690600732SDavid Daney err = phy_write(phydev, 0x15, 0x1048); 79790600732SDavid Daney if (err < 0) 79890600732SDavid Daney return err; 79990600732SDavid Daney 800cf41a51dSDavid Daney err = marvell_of_reg_init(phydev); 801cf41a51dSDavid Daney if (err < 0) 802cf41a51dSDavid Daney return err; 803cf41a51dSDavid Daney 80490600732SDavid Daney /* Reset address */ 80590600732SDavid Daney err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x0); 80690600732SDavid Daney if (err < 0) 80790600732SDavid Daney return err; 80890600732SDavid Daney 809cc90cb3bSSrinivas Kandagatla return phy_write(phydev, MII_BMCR, BMCR_RESET); 81090600732SDavid Daney } 81190600732SDavid Daney 81276884679SAndy Fleming static int m88e1145_config_init(struct phy_device *phydev) 81376884679SAndy Fleming { 81476884679SAndy Fleming int err; 815b0224175SViet Nga Dao int temp; 81676884679SAndy Fleming 81776884679SAndy Fleming /* Take care of errata E0 & E1 */ 81876884679SAndy Fleming err = phy_write(phydev, 0x1d, 0x001b); 81976884679SAndy Fleming if (err < 0) 82076884679SAndy Fleming return err; 82176884679SAndy Fleming 82276884679SAndy Fleming err = phy_write(phydev, 0x1e, 0x418f); 82376884679SAndy Fleming if (err < 0) 82476884679SAndy Fleming return err; 82576884679SAndy Fleming 82676884679SAndy Fleming err = phy_write(phydev, 0x1d, 0x0016); 82776884679SAndy Fleming if (err < 0) 82876884679SAndy Fleming return err; 82976884679SAndy Fleming 83076884679SAndy Fleming err = phy_write(phydev, 0x1e, 0xa2da); 83176884679SAndy Fleming if (err < 0) 83276884679SAndy Fleming return err; 83376884679SAndy Fleming 834895ee682SKim Phillips if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { 83576884679SAndy Fleming int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR); 83676884679SAndy Fleming if (temp < 0) 83776884679SAndy Fleming return temp; 83876884679SAndy Fleming 83976884679SAndy Fleming temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY); 84076884679SAndy Fleming 84176884679SAndy Fleming err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp); 84276884679SAndy Fleming if (err < 0) 84376884679SAndy Fleming return err; 84476884679SAndy Fleming 8452f495c39SBenjamin Herrenschmidt if (phydev->dev_flags & MARVELL_PHY_M1145_FLAGS_RESISTANCE) { 84676884679SAndy Fleming err = phy_write(phydev, 0x1d, 0x0012); 84776884679SAndy Fleming if (err < 0) 84876884679SAndy Fleming return err; 84976884679SAndy Fleming 85076884679SAndy Fleming temp = phy_read(phydev, 0x1e); 85176884679SAndy Fleming if (temp < 0) 85276884679SAndy Fleming return temp; 85376884679SAndy Fleming 85476884679SAndy Fleming temp &= 0xf03f; 85576884679SAndy Fleming temp |= 2 << 9; /* 36 ohm */ 85676884679SAndy Fleming temp |= 2 << 6; /* 39 ohm */ 85776884679SAndy Fleming 85876884679SAndy Fleming err = phy_write(phydev, 0x1e, temp); 85976884679SAndy Fleming if (err < 0) 86076884679SAndy Fleming return err; 86176884679SAndy Fleming 86276884679SAndy Fleming err = phy_write(phydev, 0x1d, 0x3); 86376884679SAndy Fleming if (err < 0) 86476884679SAndy Fleming return err; 86576884679SAndy Fleming 86676884679SAndy Fleming err = phy_write(phydev, 0x1e, 0x8000); 86776884679SAndy Fleming if (err < 0) 86876884679SAndy Fleming return err; 86976884679SAndy Fleming } 87076884679SAndy Fleming } 87176884679SAndy Fleming 872b0224175SViet Nga Dao if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { 873b0224175SViet Nga Dao temp = phy_read(phydev, MII_M1145_PHY_EXT_SR); 874b0224175SViet Nga Dao if (temp < 0) 875b0224175SViet Nga Dao return temp; 876b0224175SViet Nga Dao 87799d881f9SVince Bridgers temp &= ~MII_M1145_HWCFG_MODE_MASK; 878b0224175SViet Nga Dao temp |= MII_M1145_HWCFG_MODE_SGMII_NO_CLK; 879b0224175SViet Nga Dao temp |= MII_M1145_HWCFG_FIBER_COPPER_AUTO; 880b0224175SViet Nga Dao 881b0224175SViet Nga Dao err = phy_write(phydev, MII_M1145_PHY_EXT_SR, temp); 882b0224175SViet Nga Dao if (err < 0) 883b0224175SViet Nga Dao return err; 884b0224175SViet Nga Dao } 885b0224175SViet Nga Dao 886cf41a51dSDavid Daney err = marvell_of_reg_init(phydev); 887cf41a51dSDavid Daney if (err < 0) 888cf41a51dSDavid Daney return err; 889cf41a51dSDavid Daney 89076884679SAndy Fleming return 0; 89176884679SAndy Fleming } 89200db8189SAndy Fleming 893be937f1fSAlexandr Smirnov /* marvell_read_status 894be937f1fSAlexandr Smirnov * 895be937f1fSAlexandr Smirnov * Generic status code does not detect Fiber correctly! 896be937f1fSAlexandr Smirnov * Description: 897be937f1fSAlexandr Smirnov * Check the link, then figure out the current state 898be937f1fSAlexandr Smirnov * by comparing what we advertise with what the link partner 899be937f1fSAlexandr Smirnov * advertises. Start by checking the gigabit possibilities, 900be937f1fSAlexandr Smirnov * then move on to 10/100. 901be937f1fSAlexandr Smirnov */ 902be937f1fSAlexandr Smirnov static int marvell_read_status(struct phy_device *phydev) 903be937f1fSAlexandr Smirnov { 904be937f1fSAlexandr Smirnov int adv; 905be937f1fSAlexandr Smirnov int err; 906be937f1fSAlexandr Smirnov int lpa; 907357cd64cSRussell King int lpagb; 908be937f1fSAlexandr Smirnov int status = 0; 909be937f1fSAlexandr Smirnov 910be937f1fSAlexandr Smirnov /* Update the link, but return if there 911be937f1fSAlexandr Smirnov * was an error */ 912be937f1fSAlexandr Smirnov err = genphy_update_link(phydev); 913be937f1fSAlexandr Smirnov if (err) 914be937f1fSAlexandr Smirnov return err; 915be937f1fSAlexandr Smirnov 916be937f1fSAlexandr Smirnov if (AUTONEG_ENABLE == phydev->autoneg) { 917be937f1fSAlexandr Smirnov status = phy_read(phydev, MII_M1011_PHY_STATUS); 918be937f1fSAlexandr Smirnov if (status < 0) 919be937f1fSAlexandr Smirnov return status; 920be937f1fSAlexandr Smirnov 921be937f1fSAlexandr Smirnov lpa = phy_read(phydev, MII_LPA); 922be937f1fSAlexandr Smirnov if (lpa < 0) 923be937f1fSAlexandr Smirnov return lpa; 924be937f1fSAlexandr Smirnov 925357cd64cSRussell King lpagb = phy_read(phydev, MII_STAT1000); 926357cd64cSRussell King if (lpagb < 0) 927357cd64cSRussell King return lpagb; 928357cd64cSRussell King 929be937f1fSAlexandr Smirnov adv = phy_read(phydev, MII_ADVERTISE); 930be937f1fSAlexandr Smirnov if (adv < 0) 931be937f1fSAlexandr Smirnov return adv; 932be937f1fSAlexandr Smirnov 933357cd64cSRussell King phydev->lp_advertising = mii_stat1000_to_ethtool_lpa_t(lpagb) | 934357cd64cSRussell King mii_lpa_to_ethtool_lpa_t(lpa); 935357cd64cSRussell King 936be937f1fSAlexandr Smirnov lpa &= adv; 937be937f1fSAlexandr Smirnov 938be937f1fSAlexandr Smirnov if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) 939be937f1fSAlexandr Smirnov phydev->duplex = DUPLEX_FULL; 940be937f1fSAlexandr Smirnov else 941be937f1fSAlexandr Smirnov phydev->duplex = DUPLEX_HALF; 942be937f1fSAlexandr Smirnov 943be937f1fSAlexandr Smirnov status = status & MII_M1011_PHY_STATUS_SPD_MASK; 944be937f1fSAlexandr Smirnov phydev->pause = phydev->asym_pause = 0; 945be937f1fSAlexandr Smirnov 946be937f1fSAlexandr Smirnov switch (status) { 947be937f1fSAlexandr Smirnov case MII_M1011_PHY_STATUS_1000: 948be937f1fSAlexandr Smirnov phydev->speed = SPEED_1000; 949be937f1fSAlexandr Smirnov break; 950be937f1fSAlexandr Smirnov 951be937f1fSAlexandr Smirnov case MII_M1011_PHY_STATUS_100: 952be937f1fSAlexandr Smirnov phydev->speed = SPEED_100; 953be937f1fSAlexandr Smirnov break; 954be937f1fSAlexandr Smirnov 955be937f1fSAlexandr Smirnov default: 956be937f1fSAlexandr Smirnov phydev->speed = SPEED_10; 957be937f1fSAlexandr Smirnov break; 958be937f1fSAlexandr Smirnov } 959be937f1fSAlexandr Smirnov 960be937f1fSAlexandr Smirnov if (phydev->duplex == DUPLEX_FULL) { 961be937f1fSAlexandr Smirnov phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; 962be937f1fSAlexandr Smirnov phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; 963be937f1fSAlexandr Smirnov } 964be937f1fSAlexandr Smirnov } else { 965be937f1fSAlexandr Smirnov int bmcr = phy_read(phydev, MII_BMCR); 966be937f1fSAlexandr Smirnov 967be937f1fSAlexandr Smirnov if (bmcr < 0) 968be937f1fSAlexandr Smirnov return bmcr; 969be937f1fSAlexandr Smirnov 970be937f1fSAlexandr Smirnov if (bmcr & BMCR_FULLDPLX) 971be937f1fSAlexandr Smirnov phydev->duplex = DUPLEX_FULL; 972be937f1fSAlexandr Smirnov else 973be937f1fSAlexandr Smirnov phydev->duplex = DUPLEX_HALF; 974be937f1fSAlexandr Smirnov 975be937f1fSAlexandr Smirnov if (bmcr & BMCR_SPEED1000) 976be937f1fSAlexandr Smirnov phydev->speed = SPEED_1000; 977be937f1fSAlexandr Smirnov else if (bmcr & BMCR_SPEED100) 978be937f1fSAlexandr Smirnov phydev->speed = SPEED_100; 979be937f1fSAlexandr Smirnov else 980be937f1fSAlexandr Smirnov phydev->speed = SPEED_10; 981be937f1fSAlexandr Smirnov 982be937f1fSAlexandr Smirnov phydev->pause = phydev->asym_pause = 0; 983357cd64cSRussell King phydev->lp_advertising = 0; 984be937f1fSAlexandr Smirnov } 985be937f1fSAlexandr Smirnov 986be937f1fSAlexandr Smirnov return 0; 987be937f1fSAlexandr Smirnov } 988be937f1fSAlexandr Smirnov 9896b358aedSSebastian Hesselbarth static int marvell_aneg_done(struct phy_device *phydev) 9906b358aedSSebastian Hesselbarth { 9916b358aedSSebastian Hesselbarth int retval = phy_read(phydev, MII_M1011_PHY_STATUS); 9926b358aedSSebastian Hesselbarth return (retval < 0) ? retval : (retval & MII_M1011_PHY_STATUS_RESOLVED); 9936b358aedSSebastian Hesselbarth } 9946b358aedSSebastian Hesselbarth 995dcd07be3SAnatolij Gustschin static int m88e1121_did_interrupt(struct phy_device *phydev) 996dcd07be3SAnatolij Gustschin { 997dcd07be3SAnatolij Gustschin int imask; 998dcd07be3SAnatolij Gustschin 999dcd07be3SAnatolij Gustschin imask = phy_read(phydev, MII_M1011_IEVENT); 1000dcd07be3SAnatolij Gustschin 1001dcd07be3SAnatolij Gustschin if (imask & MII_M1011_IMASK_INIT) 1002dcd07be3SAnatolij Gustschin return 1; 1003dcd07be3SAnatolij Gustschin 1004dcd07be3SAnatolij Gustschin return 0; 1005dcd07be3SAnatolij Gustschin } 1006dcd07be3SAnatolij Gustschin 10073871c387SMichael Stapelberg static void m88e1318_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) 10083871c387SMichael Stapelberg { 10093871c387SMichael Stapelberg wol->supported = WAKE_MAGIC; 10103871c387SMichael Stapelberg wol->wolopts = 0; 10113871c387SMichael Stapelberg 10123871c387SMichael Stapelberg if (phy_write(phydev, MII_MARVELL_PHY_PAGE, 10133871c387SMichael Stapelberg MII_88E1318S_PHY_WOL_PAGE) < 0) 10143871c387SMichael Stapelberg return; 10153871c387SMichael Stapelberg 10163871c387SMichael Stapelberg if (phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL) & 10173871c387SMichael Stapelberg MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE) 10183871c387SMichael Stapelberg wol->wolopts |= WAKE_MAGIC; 10193871c387SMichael Stapelberg 10203871c387SMichael Stapelberg if (phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x00) < 0) 10213871c387SMichael Stapelberg return; 10223871c387SMichael Stapelberg } 10233871c387SMichael Stapelberg 10243871c387SMichael Stapelberg static int m88e1318_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) 10253871c387SMichael Stapelberg { 10263871c387SMichael Stapelberg int err, oldpage, temp; 10273871c387SMichael Stapelberg 10283871c387SMichael Stapelberg oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); 10293871c387SMichael Stapelberg 10303871c387SMichael Stapelberg if (wol->wolopts & WAKE_MAGIC) { 10313871c387SMichael Stapelberg /* Explicitly switch to page 0x00, just to be sure */ 10323871c387SMichael Stapelberg err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 0x00); 10333871c387SMichael Stapelberg if (err < 0) 10343871c387SMichael Stapelberg return err; 10353871c387SMichael Stapelberg 10363871c387SMichael Stapelberg /* Enable the WOL interrupt */ 10373871c387SMichael Stapelberg temp = phy_read(phydev, MII_88E1318S_PHY_CSIER); 10383871c387SMichael Stapelberg temp |= MII_88E1318S_PHY_CSIER_WOL_EIE; 10393871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_CSIER, temp); 10403871c387SMichael Stapelberg if (err < 0) 10413871c387SMichael Stapelberg return err; 10423871c387SMichael Stapelberg 10433871c387SMichael Stapelberg err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 10443871c387SMichael Stapelberg MII_88E1318S_PHY_LED_PAGE); 10453871c387SMichael Stapelberg if (err < 0) 10463871c387SMichael Stapelberg return err; 10473871c387SMichael Stapelberg 10483871c387SMichael Stapelberg /* Setup LED[2] as interrupt pin (active low) */ 10493871c387SMichael Stapelberg temp = phy_read(phydev, MII_88E1318S_PHY_LED_TCR); 10503871c387SMichael Stapelberg temp &= ~MII_88E1318S_PHY_LED_TCR_FORCE_INT; 10513871c387SMichael Stapelberg temp |= MII_88E1318S_PHY_LED_TCR_INTn_ENABLE; 10523871c387SMichael Stapelberg temp |= MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW; 10533871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_LED_TCR, temp); 10543871c387SMichael Stapelberg if (err < 0) 10553871c387SMichael Stapelberg return err; 10563871c387SMichael Stapelberg 10573871c387SMichael Stapelberg err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 10583871c387SMichael Stapelberg MII_88E1318S_PHY_WOL_PAGE); 10593871c387SMichael Stapelberg if (err < 0) 10603871c387SMichael Stapelberg return err; 10613871c387SMichael Stapelberg 10623871c387SMichael Stapelberg /* Store the device address for the magic packet */ 10633871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD2, 10643871c387SMichael Stapelberg ((phydev->attached_dev->dev_addr[5] << 8) | 10653871c387SMichael Stapelberg phydev->attached_dev->dev_addr[4])); 10663871c387SMichael Stapelberg if (err < 0) 10673871c387SMichael Stapelberg return err; 10683871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD1, 10693871c387SMichael Stapelberg ((phydev->attached_dev->dev_addr[3] << 8) | 10703871c387SMichael Stapelberg phydev->attached_dev->dev_addr[2])); 10713871c387SMichael Stapelberg if (err < 0) 10723871c387SMichael Stapelberg return err; 10733871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD0, 10743871c387SMichael Stapelberg ((phydev->attached_dev->dev_addr[1] << 8) | 10753871c387SMichael Stapelberg phydev->attached_dev->dev_addr[0])); 10763871c387SMichael Stapelberg if (err < 0) 10773871c387SMichael Stapelberg return err; 10783871c387SMichael Stapelberg 10793871c387SMichael Stapelberg /* Clear WOL status and enable magic packet matching */ 10803871c387SMichael Stapelberg temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL); 10813871c387SMichael Stapelberg temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS; 10823871c387SMichael Stapelberg temp |= MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE; 10833871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp); 10843871c387SMichael Stapelberg if (err < 0) 10853871c387SMichael Stapelberg return err; 10863871c387SMichael Stapelberg } else { 10873871c387SMichael Stapelberg err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 10883871c387SMichael Stapelberg MII_88E1318S_PHY_WOL_PAGE); 10893871c387SMichael Stapelberg if (err < 0) 10903871c387SMichael Stapelberg return err; 10913871c387SMichael Stapelberg 10923871c387SMichael Stapelberg /* Clear WOL status and disable magic packet matching */ 10933871c387SMichael Stapelberg temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL); 10943871c387SMichael Stapelberg temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS; 10953871c387SMichael Stapelberg temp &= ~MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE; 10963871c387SMichael Stapelberg err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp); 10973871c387SMichael Stapelberg if (err < 0) 10983871c387SMichael Stapelberg return err; 10993871c387SMichael Stapelberg } 11003871c387SMichael Stapelberg 11013871c387SMichael Stapelberg err = phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage); 11023871c387SMichael Stapelberg if (err < 0) 11033871c387SMichael Stapelberg return err; 11043871c387SMichael Stapelberg 11053871c387SMichael Stapelberg return 0; 11063871c387SMichael Stapelberg } 11073871c387SMichael Stapelberg 1108d2fa47d9SAndrew Lunn static int marvell_get_sset_count(struct phy_device *phydev) 1109d2fa47d9SAndrew Lunn { 1110d2fa47d9SAndrew Lunn return ARRAY_SIZE(marvell_hw_stats); 1111d2fa47d9SAndrew Lunn } 1112d2fa47d9SAndrew Lunn 1113d2fa47d9SAndrew Lunn static void marvell_get_strings(struct phy_device *phydev, u8 *data) 1114d2fa47d9SAndrew Lunn { 1115d2fa47d9SAndrew Lunn int i; 1116d2fa47d9SAndrew Lunn 1117d2fa47d9SAndrew Lunn for (i = 0; i < ARRAY_SIZE(marvell_hw_stats); i++) { 1118d2fa47d9SAndrew Lunn memcpy(data + i * ETH_GSTRING_LEN, 1119d2fa47d9SAndrew Lunn marvell_hw_stats[i].string, ETH_GSTRING_LEN); 1120d2fa47d9SAndrew Lunn } 1121d2fa47d9SAndrew Lunn } 1122d2fa47d9SAndrew Lunn 1123d2fa47d9SAndrew Lunn #ifndef UINT64_MAX 1124d2fa47d9SAndrew Lunn #define UINT64_MAX (u64)(~((u64)0)) 1125d2fa47d9SAndrew Lunn #endif 1126d2fa47d9SAndrew Lunn static u64 marvell_get_stat(struct phy_device *phydev, int i) 1127d2fa47d9SAndrew Lunn { 1128d2fa47d9SAndrew Lunn struct marvell_hw_stat stat = marvell_hw_stats[i]; 1129d2fa47d9SAndrew Lunn struct marvell_priv *priv = phydev->priv; 1130321b4d4bSAndrew Lunn int err, oldpage, val; 1131321b4d4bSAndrew Lunn u64 ret; 1132d2fa47d9SAndrew Lunn 1133d2fa47d9SAndrew Lunn oldpage = phy_read(phydev, MII_MARVELL_PHY_PAGE); 1134d2fa47d9SAndrew Lunn err = phy_write(phydev, MII_MARVELL_PHY_PAGE, 1135d2fa47d9SAndrew Lunn stat.page); 1136d2fa47d9SAndrew Lunn if (err < 0) 1137d2fa47d9SAndrew Lunn return UINT64_MAX; 1138d2fa47d9SAndrew Lunn 1139d2fa47d9SAndrew Lunn val = phy_read(phydev, stat.reg); 1140d2fa47d9SAndrew Lunn if (val < 0) { 1141321b4d4bSAndrew Lunn ret = UINT64_MAX; 1142d2fa47d9SAndrew Lunn } else { 1143d2fa47d9SAndrew Lunn val = val & ((1 << stat.bits) - 1); 1144d2fa47d9SAndrew Lunn priv->stats[i] += val; 1145321b4d4bSAndrew Lunn ret = priv->stats[i]; 1146d2fa47d9SAndrew Lunn } 1147d2fa47d9SAndrew Lunn 1148d2fa47d9SAndrew Lunn phy_write(phydev, MII_MARVELL_PHY_PAGE, oldpage); 1149d2fa47d9SAndrew Lunn 1150321b4d4bSAndrew Lunn return ret; 1151d2fa47d9SAndrew Lunn } 1152d2fa47d9SAndrew Lunn 1153d2fa47d9SAndrew Lunn static void marvell_get_stats(struct phy_device *phydev, 1154d2fa47d9SAndrew Lunn struct ethtool_stats *stats, u64 *data) 1155d2fa47d9SAndrew Lunn { 1156d2fa47d9SAndrew Lunn int i; 1157d2fa47d9SAndrew Lunn 1158d2fa47d9SAndrew Lunn for (i = 0; i < ARRAY_SIZE(marvell_hw_stats); i++) 1159d2fa47d9SAndrew Lunn data[i] = marvell_get_stat(phydev, i); 1160d2fa47d9SAndrew Lunn } 1161d2fa47d9SAndrew Lunn 1162d2fa47d9SAndrew Lunn static int marvell_probe(struct phy_device *phydev) 1163d2fa47d9SAndrew Lunn { 1164d2fa47d9SAndrew Lunn struct marvell_priv *priv; 1165d2fa47d9SAndrew Lunn 1166e5a03bfdSAndrew Lunn priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); 1167d2fa47d9SAndrew Lunn if (!priv) 1168d2fa47d9SAndrew Lunn return -ENOMEM; 1169d2fa47d9SAndrew Lunn 1170d2fa47d9SAndrew Lunn phydev->priv = priv; 1171d2fa47d9SAndrew Lunn 1172d2fa47d9SAndrew Lunn return 0; 1173d2fa47d9SAndrew Lunn } 1174d2fa47d9SAndrew Lunn 1175e5479239SOlof Johansson static struct phy_driver marvell_drivers[] = { 1176e5479239SOlof Johansson { 11772f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1101, 11782f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 117900db8189SAndy Fleming .name = "Marvell 88E1101", 118000db8189SAndy Fleming .features = PHY_GBIT_FEATURES, 1181d2fa47d9SAndrew Lunn .probe = marvell_probe, 118200db8189SAndy Fleming .flags = PHY_HAS_INTERRUPT, 118379be1a1cSClemens Gruber .config_init = &marvell_config_init, 118400db8189SAndy Fleming .config_aneg = &marvell_config_aneg, 118500db8189SAndy Fleming .read_status = &genphy_read_status, 118600db8189SAndy Fleming .ack_interrupt = &marvell_ack_interrupt, 118700db8189SAndy Fleming .config_intr = &marvell_config_intr, 11880898b448SSebastian Hesselbarth .resume = &genphy_resume, 11890898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 1190d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1191d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1192d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 1193e5479239SOlof Johansson }, 1194e5479239SOlof Johansson { 11952f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1112, 11962f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 119785cfb534SOlof Johansson .name = "Marvell 88E1112", 119885cfb534SOlof Johansson .features = PHY_GBIT_FEATURES, 119985cfb534SOlof Johansson .flags = PHY_HAS_INTERRUPT, 1200d2fa47d9SAndrew Lunn .probe = marvell_probe, 120185cfb534SOlof Johansson .config_init = &m88e1111_config_init, 120285cfb534SOlof Johansson .config_aneg = &marvell_config_aneg, 120385cfb534SOlof Johansson .read_status = &genphy_read_status, 120485cfb534SOlof Johansson .ack_interrupt = &marvell_ack_interrupt, 120585cfb534SOlof Johansson .config_intr = &marvell_config_intr, 12060898b448SSebastian Hesselbarth .resume = &genphy_resume, 12070898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 1208d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1209d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1210d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 121185cfb534SOlof Johansson }, 121285cfb534SOlof Johansson { 12132f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1111, 12142f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 121576884679SAndy Fleming .name = "Marvell 88E1111", 121676884679SAndy Fleming .features = PHY_GBIT_FEATURES, 121776884679SAndy Fleming .flags = PHY_HAS_INTERRUPT, 1218d2fa47d9SAndrew Lunn .probe = marvell_probe, 1219e5479239SOlof Johansson .config_init = &m88e1111_config_init, 12203ec0a0f1SHarini Katakam .config_aneg = &m88e1111_config_aneg, 1221be937f1fSAlexandr Smirnov .read_status = &marvell_read_status, 122276884679SAndy Fleming .ack_interrupt = &marvell_ack_interrupt, 122376884679SAndy Fleming .config_intr = &marvell_config_intr, 12240898b448SSebastian Hesselbarth .resume = &genphy_resume, 12250898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 1226d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1227d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1228d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 1229e5479239SOlof Johansson }, 1230e5479239SOlof Johansson { 12312f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1118, 12322f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 1233605f196eSRon Madrid .name = "Marvell 88E1118", 1234605f196eSRon Madrid .features = PHY_GBIT_FEATURES, 1235605f196eSRon Madrid .flags = PHY_HAS_INTERRUPT, 1236d2fa47d9SAndrew Lunn .probe = marvell_probe, 1237605f196eSRon Madrid .config_init = &m88e1118_config_init, 1238605f196eSRon Madrid .config_aneg = &m88e1118_config_aneg, 1239605f196eSRon Madrid .read_status = &genphy_read_status, 1240605f196eSRon Madrid .ack_interrupt = &marvell_ack_interrupt, 1241605f196eSRon Madrid .config_intr = &marvell_config_intr, 12420898b448SSebastian Hesselbarth .resume = &genphy_resume, 12430898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 1244d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1245d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1246d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 1247605f196eSRon Madrid }, 1248605f196eSRon Madrid { 12492f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1121R, 12502f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 1251140bc929SSergei Poselenov .name = "Marvell 88E1121R", 1252140bc929SSergei Poselenov .features = PHY_GBIT_FEATURES, 1253140bc929SSergei Poselenov .flags = PHY_HAS_INTERRUPT, 1254d2fa47d9SAndrew Lunn .probe = marvell_probe, 1255fdecf36fSClemens Gruber .config_init = &m88e1121_config_init, 1256140bc929SSergei Poselenov .config_aneg = &m88e1121_config_aneg, 1257140bc929SSergei Poselenov .read_status = &marvell_read_status, 1258140bc929SSergei Poselenov .ack_interrupt = &marvell_ack_interrupt, 1259140bc929SSergei Poselenov .config_intr = &marvell_config_intr, 1260dcd07be3SAnatolij Gustschin .did_interrupt = &m88e1121_did_interrupt, 12610898b448SSebastian Hesselbarth .resume = &genphy_resume, 12620898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 1263d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1264d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1265d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 1266140bc929SSergei Poselenov }, 1267140bc929SSergei Poselenov { 1268337ac9d5SCyril Chemparathy .phy_id = MARVELL_PHY_ID_88E1318S, 12696ba74014SLinus Torvalds .phy_id_mask = MARVELL_PHY_ID_MASK, 1270337ac9d5SCyril Chemparathy .name = "Marvell 88E1318S", 12713ff1c259SCyril Chemparathy .features = PHY_GBIT_FEATURES, 12723ff1c259SCyril Chemparathy .flags = PHY_HAS_INTERRUPT, 1273d2fa47d9SAndrew Lunn .probe = marvell_probe, 1274fdecf36fSClemens Gruber .config_init = &m88e1121_config_init, 1275337ac9d5SCyril Chemparathy .config_aneg = &m88e1318_config_aneg, 12763ff1c259SCyril Chemparathy .read_status = &marvell_read_status, 12773ff1c259SCyril Chemparathy .ack_interrupt = &marvell_ack_interrupt, 12783ff1c259SCyril Chemparathy .config_intr = &marvell_config_intr, 12793ff1c259SCyril Chemparathy .did_interrupt = &m88e1121_did_interrupt, 12803871c387SMichael Stapelberg .get_wol = &m88e1318_get_wol, 12813871c387SMichael Stapelberg .set_wol = &m88e1318_set_wol, 12820898b448SSebastian Hesselbarth .resume = &genphy_resume, 12830898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 1284d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1285d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1286d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 12873ff1c259SCyril Chemparathy }, 12883ff1c259SCyril Chemparathy { 12892f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1145, 12902f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 129176884679SAndy Fleming .name = "Marvell 88E1145", 129276884679SAndy Fleming .features = PHY_GBIT_FEATURES, 129376884679SAndy Fleming .flags = PHY_HAS_INTERRUPT, 1294d2fa47d9SAndrew Lunn .probe = marvell_probe, 129576884679SAndy Fleming .config_init = &m88e1145_config_init, 129676884679SAndy Fleming .config_aneg = &marvell_config_aneg, 129776884679SAndy Fleming .read_status = &genphy_read_status, 129876884679SAndy Fleming .ack_interrupt = &marvell_ack_interrupt, 129976884679SAndy Fleming .config_intr = &marvell_config_intr, 13000898b448SSebastian Hesselbarth .resume = &genphy_resume, 13010898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 1302d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1303d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1304d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 1305ac8c635aSOlof Johansson }, 1306ac8c635aSOlof Johansson { 130790600732SDavid Daney .phy_id = MARVELL_PHY_ID_88E1149R, 130890600732SDavid Daney .phy_id_mask = MARVELL_PHY_ID_MASK, 130990600732SDavid Daney .name = "Marvell 88E1149R", 131090600732SDavid Daney .features = PHY_GBIT_FEATURES, 131190600732SDavid Daney .flags = PHY_HAS_INTERRUPT, 1312d2fa47d9SAndrew Lunn .probe = marvell_probe, 131390600732SDavid Daney .config_init = &m88e1149_config_init, 131490600732SDavid Daney .config_aneg = &m88e1118_config_aneg, 131590600732SDavid Daney .read_status = &genphy_read_status, 131690600732SDavid Daney .ack_interrupt = &marvell_ack_interrupt, 131790600732SDavid Daney .config_intr = &marvell_config_intr, 13180898b448SSebastian Hesselbarth .resume = &genphy_resume, 13190898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 1320d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1321d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1322d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 132390600732SDavid Daney }, 132490600732SDavid Daney { 13252f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1240, 13262f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 1327ac8c635aSOlof Johansson .name = "Marvell 88E1240", 1328ac8c635aSOlof Johansson .features = PHY_GBIT_FEATURES, 1329ac8c635aSOlof Johansson .flags = PHY_HAS_INTERRUPT, 1330d2fa47d9SAndrew Lunn .probe = marvell_probe, 1331ac8c635aSOlof Johansson .config_init = &m88e1111_config_init, 1332ac8c635aSOlof Johansson .config_aneg = &marvell_config_aneg, 1333ac8c635aSOlof Johansson .read_status = &genphy_read_status, 1334ac8c635aSOlof Johansson .ack_interrupt = &marvell_ack_interrupt, 1335ac8c635aSOlof Johansson .config_intr = &marvell_config_intr, 13360898b448SSebastian Hesselbarth .resume = &genphy_resume, 13370898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 1338d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1339d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1340d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 1341ac8c635aSOlof Johansson }, 13423da09a51SMichal Simek { 13433da09a51SMichal Simek .phy_id = MARVELL_PHY_ID_88E1116R, 13443da09a51SMichal Simek .phy_id_mask = MARVELL_PHY_ID_MASK, 13453da09a51SMichal Simek .name = "Marvell 88E1116R", 13463da09a51SMichal Simek .features = PHY_GBIT_FEATURES, 13473da09a51SMichal Simek .flags = PHY_HAS_INTERRUPT, 1348d2fa47d9SAndrew Lunn .probe = marvell_probe, 13493da09a51SMichal Simek .config_init = &m88e1116r_config_init, 13503da09a51SMichal Simek .config_aneg = &genphy_config_aneg, 13513da09a51SMichal Simek .read_status = &genphy_read_status, 13523da09a51SMichal Simek .ack_interrupt = &marvell_ack_interrupt, 13533da09a51SMichal Simek .config_intr = &marvell_config_intr, 13540898b448SSebastian Hesselbarth .resume = &genphy_resume, 13550898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 1356d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1357d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1358d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 13593da09a51SMichal Simek }, 136010e24caaSMichal Simek { 136110e24caaSMichal Simek .phy_id = MARVELL_PHY_ID_88E1510, 136210e24caaSMichal Simek .phy_id_mask = MARVELL_PHY_ID_MASK, 136310e24caaSMichal Simek .name = "Marvell 88E1510", 136410e24caaSMichal Simek .features = PHY_GBIT_FEATURES, 136510e24caaSMichal Simek .flags = PHY_HAS_INTERRUPT, 1366d2fa47d9SAndrew Lunn .probe = marvell_probe, 1367930b37eeSStefan Roese .config_init = &m88e1510_config_init, 136810e24caaSMichal Simek .config_aneg = &m88e1510_config_aneg, 136910e24caaSMichal Simek .read_status = &marvell_read_status, 137010e24caaSMichal Simek .ack_interrupt = &marvell_ack_interrupt, 137110e24caaSMichal Simek .config_intr = &marvell_config_intr, 137210e24caaSMichal Simek .did_interrupt = &m88e1121_did_interrupt, 13730898b448SSebastian Hesselbarth .resume = &genphy_resume, 13740898b448SSebastian Hesselbarth .suspend = &genphy_suspend, 1375d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1376d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1377d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 137810e24caaSMichal Simek }, 13796b358aedSSebastian Hesselbarth { 1380819ec8e1SAndrew Lunn .phy_id = MARVELL_PHY_ID_88E1540, 1381819ec8e1SAndrew Lunn .phy_id_mask = MARVELL_PHY_ID_MASK, 1382819ec8e1SAndrew Lunn .name = "Marvell 88E1540", 1383819ec8e1SAndrew Lunn .features = PHY_GBIT_FEATURES, 1384819ec8e1SAndrew Lunn .flags = PHY_HAS_INTERRUPT, 1385d2fa47d9SAndrew Lunn .probe = marvell_probe, 138679be1a1cSClemens Gruber .config_init = &marvell_config_init, 1387819ec8e1SAndrew Lunn .config_aneg = &m88e1510_config_aneg, 1388819ec8e1SAndrew Lunn .read_status = &marvell_read_status, 1389819ec8e1SAndrew Lunn .ack_interrupt = &marvell_ack_interrupt, 1390819ec8e1SAndrew Lunn .config_intr = &marvell_config_intr, 1391819ec8e1SAndrew Lunn .did_interrupt = &m88e1121_did_interrupt, 1392819ec8e1SAndrew Lunn .resume = &genphy_resume, 1393819ec8e1SAndrew Lunn .suspend = &genphy_suspend, 1394d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1395d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1396d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 1397819ec8e1SAndrew Lunn }, 1398819ec8e1SAndrew Lunn { 13996b358aedSSebastian Hesselbarth .phy_id = MARVELL_PHY_ID_88E3016, 14006b358aedSSebastian Hesselbarth .phy_id_mask = MARVELL_PHY_ID_MASK, 14016b358aedSSebastian Hesselbarth .name = "Marvell 88E3016", 14026b358aedSSebastian Hesselbarth .features = PHY_BASIC_FEATURES, 14036b358aedSSebastian Hesselbarth .flags = PHY_HAS_INTERRUPT, 1404d2fa47d9SAndrew Lunn .probe = marvell_probe, 14056b358aedSSebastian Hesselbarth .config_aneg = &genphy_config_aneg, 14066b358aedSSebastian Hesselbarth .config_init = &m88e3016_config_init, 14076b358aedSSebastian Hesselbarth .aneg_done = &marvell_aneg_done, 14086b358aedSSebastian Hesselbarth .read_status = &marvell_read_status, 14096b358aedSSebastian Hesselbarth .ack_interrupt = &marvell_ack_interrupt, 14106b358aedSSebastian Hesselbarth .config_intr = &marvell_config_intr, 14116b358aedSSebastian Hesselbarth .did_interrupt = &m88e1121_did_interrupt, 14126b358aedSSebastian Hesselbarth .resume = &genphy_resume, 14136b358aedSSebastian Hesselbarth .suspend = &genphy_suspend, 1414d2fa47d9SAndrew Lunn .get_sset_count = marvell_get_sset_count, 1415d2fa47d9SAndrew Lunn .get_strings = marvell_get_strings, 1416d2fa47d9SAndrew Lunn .get_stats = marvell_get_stats, 14176b358aedSSebastian Hesselbarth }, 141876884679SAndy Fleming }; 141976884679SAndy Fleming 142050fd7150SJohan Hovold module_phy_driver(marvell_drivers); 14214e4f10f6SDavid Woodhouse 1422cf93c945SUwe Kleine-König static struct mdio_device_id __maybe_unused marvell_tbl[] = { 1423f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1101, MARVELL_PHY_ID_MASK }, 1424f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1112, MARVELL_PHY_ID_MASK }, 1425f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1111, MARVELL_PHY_ID_MASK }, 1426f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1118, MARVELL_PHY_ID_MASK }, 1427f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1121R, MARVELL_PHY_ID_MASK }, 1428f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1145, MARVELL_PHY_ID_MASK }, 1429f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1149R, MARVELL_PHY_ID_MASK }, 1430f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1240, MARVELL_PHY_ID_MASK }, 1431f5e1cabfSMichal Simek { MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK }, 14323da09a51SMichal Simek { MARVELL_PHY_ID_88E1116R, MARVELL_PHY_ID_MASK }, 143310e24caaSMichal Simek { MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK }, 1434819ec8e1SAndrew Lunn { MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK }, 14356b358aedSSebastian Hesselbarth { MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK }, 14364e4f10f6SDavid Woodhouse { } 14374e4f10f6SDavid Woodhouse }; 14384e4f10f6SDavid Woodhouse 14394e4f10f6SDavid Woodhouse MODULE_DEVICE_TABLE(mdio, marvell_tbl); 1440