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 * 1000db8189SAndy Fleming * This program is free software; you can redistribute it and/or modify it 1100db8189SAndy Fleming * under the terms of the GNU General Public License as published by the 1200db8189SAndy Fleming * Free Software Foundation; either version 2 of the License, or (at your 1300db8189SAndy Fleming * option) any later version. 1400db8189SAndy Fleming * 1500db8189SAndy Fleming */ 1600db8189SAndy Fleming #include <linux/kernel.h> 1700db8189SAndy Fleming #include <linux/string.h> 1800db8189SAndy Fleming #include <linux/errno.h> 1900db8189SAndy Fleming #include <linux/unistd.h> 2000db8189SAndy Fleming #include <linux/interrupt.h> 2100db8189SAndy Fleming #include <linux/init.h> 2200db8189SAndy Fleming #include <linux/delay.h> 2300db8189SAndy Fleming #include <linux/netdevice.h> 2400db8189SAndy Fleming #include <linux/etherdevice.h> 2500db8189SAndy Fleming #include <linux/skbuff.h> 2600db8189SAndy Fleming #include <linux/spinlock.h> 2700db8189SAndy Fleming #include <linux/mm.h> 2800db8189SAndy Fleming #include <linux/module.h> 2900db8189SAndy Fleming #include <linux/mii.h> 3000db8189SAndy Fleming #include <linux/ethtool.h> 3100db8189SAndy Fleming #include <linux/phy.h> 322f495c39SBenjamin Herrenschmidt #include <linux/marvell_phy.h> 3300db8189SAndy Fleming 3400db8189SAndy Fleming #include <asm/io.h> 3500db8189SAndy Fleming #include <asm/irq.h> 3600db8189SAndy Fleming #include <asm/uaccess.h> 3700db8189SAndy Fleming 3800db8189SAndy Fleming #define MII_M1011_IEVENT 0x13 3900db8189SAndy Fleming #define MII_M1011_IEVENT_CLEAR 0x0000 4000db8189SAndy Fleming 4100db8189SAndy Fleming #define MII_M1011_IMASK 0x12 4200db8189SAndy Fleming #define MII_M1011_IMASK_INIT 0x6400 4300db8189SAndy Fleming #define MII_M1011_IMASK_CLEAR 0x0000 4400db8189SAndy Fleming 4576884679SAndy Fleming #define MII_M1011_PHY_SCR 0x10 4676884679SAndy Fleming #define MII_M1011_PHY_SCR_AUTO_CROSS 0x0060 4776884679SAndy Fleming 4876884679SAndy Fleming #define MII_M1145_PHY_EXT_CR 0x14 4976884679SAndy Fleming #define MII_M1145_RGMII_RX_DELAY 0x0080 5076884679SAndy Fleming #define MII_M1145_RGMII_TX_DELAY 0x0002 5176884679SAndy Fleming 5276884679SAndy Fleming #define MII_M1111_PHY_LED_CONTROL 0x18 5376884679SAndy Fleming #define MII_M1111_PHY_LED_DIRECT 0x4100 5476884679SAndy Fleming #define MII_M1111_PHY_LED_COMBINE 0x411c 55895ee682SKim Phillips #define MII_M1111_PHY_EXT_CR 0x14 56895ee682SKim Phillips #define MII_M1111_RX_DELAY 0x80 57895ee682SKim Phillips #define MII_M1111_TX_DELAY 0x2 58895ee682SKim Phillips #define MII_M1111_PHY_EXT_SR 0x1b 59be937f1fSAlexandr Smirnov 60895ee682SKim Phillips #define MII_M1111_HWCFG_MODE_MASK 0xf 61be937f1fSAlexandr Smirnov #define MII_M1111_HWCFG_MODE_COPPER_RGMII 0xb 62be937f1fSAlexandr Smirnov #define MII_M1111_HWCFG_MODE_FIBER_RGMII 0x3 634117b5beSKapil Juneja #define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4 645f8cbc13SLiu Yu-B13201 #define MII_M1111_HWCFG_MODE_COPPER_RTBI 0x9 65be937f1fSAlexandr Smirnov #define MII_M1111_HWCFG_FIBER_COPPER_AUTO 0x8000 66be937f1fSAlexandr Smirnov #define MII_M1111_HWCFG_FIBER_COPPER_RES 0x2000 67be937f1fSAlexandr Smirnov 68be937f1fSAlexandr Smirnov #define MII_M1111_COPPER 0 69be937f1fSAlexandr Smirnov #define MII_M1111_FIBER 1 70be937f1fSAlexandr Smirnov 71c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_PAGE 2 72c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_REG 21 73c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_RX_DELAY BIT(5) 74c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4) 75c477d044SCyril Chemparathy #define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4)) 76c477d044SCyril Chemparathy 77337ac9d5SCyril Chemparathy #define MII_88E1318S_PHY_MSCR1_REG 16 78337ac9d5SCyril Chemparathy #define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6) 793ff1c259SCyril Chemparathy 80140bc929SSergei Poselenov #define MII_88E1121_PHY_LED_CTRL 16 81140bc929SSergei Poselenov #define MII_88E1121_PHY_LED_PAGE 3 82140bc929SSergei Poselenov #define MII_88E1121_PHY_LED_DEF 0x0030 83140bc929SSergei Poselenov #define MII_88E1121_PHY_PAGE 22 84140bc929SSergei Poselenov 85be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS 0x11 86be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_1000 0x8000 87be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_100 0x4000 88be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_SPD_MASK 0xc000 89be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000 90be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_RESOLVED 0x0800 91be937f1fSAlexandr Smirnov #define MII_M1011_PHY_STATUS_LINK 0x0400 92be937f1fSAlexandr Smirnov 9376884679SAndy Fleming 9400db8189SAndy Fleming MODULE_DESCRIPTION("Marvell PHY driver"); 9500db8189SAndy Fleming MODULE_AUTHOR("Andy Fleming"); 9600db8189SAndy Fleming MODULE_LICENSE("GPL"); 9700db8189SAndy Fleming 9800db8189SAndy Fleming static int marvell_ack_interrupt(struct phy_device *phydev) 9900db8189SAndy Fleming { 10000db8189SAndy Fleming int err; 10100db8189SAndy Fleming 10200db8189SAndy Fleming /* Clear the interrupts by reading the reg */ 10300db8189SAndy Fleming err = phy_read(phydev, MII_M1011_IEVENT); 10400db8189SAndy Fleming 10500db8189SAndy Fleming if (err < 0) 10600db8189SAndy Fleming return err; 10700db8189SAndy Fleming 10800db8189SAndy Fleming return 0; 10900db8189SAndy Fleming } 11000db8189SAndy Fleming 11100db8189SAndy Fleming static int marvell_config_intr(struct phy_device *phydev) 11200db8189SAndy Fleming { 11300db8189SAndy Fleming int err; 11400db8189SAndy Fleming 11500db8189SAndy Fleming if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 11600db8189SAndy Fleming err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT); 11700db8189SAndy Fleming else 11800db8189SAndy Fleming err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); 11900db8189SAndy Fleming 12000db8189SAndy Fleming return err; 12100db8189SAndy Fleming } 12200db8189SAndy Fleming 12300db8189SAndy Fleming static int marvell_config_aneg(struct phy_device *phydev) 12400db8189SAndy Fleming { 12500db8189SAndy Fleming int err; 12600db8189SAndy Fleming 12700db8189SAndy Fleming /* The Marvell PHY has an errata which requires 12800db8189SAndy Fleming * that certain registers get written in order 12900db8189SAndy Fleming * to restart autonegotiation */ 13000db8189SAndy Fleming err = phy_write(phydev, MII_BMCR, BMCR_RESET); 13100db8189SAndy Fleming 13200db8189SAndy Fleming if (err < 0) 13300db8189SAndy Fleming return err; 13400db8189SAndy Fleming 13500db8189SAndy Fleming err = phy_write(phydev, 0x1d, 0x1f); 13600db8189SAndy Fleming if (err < 0) 13700db8189SAndy Fleming return err; 13800db8189SAndy Fleming 13900db8189SAndy Fleming err = phy_write(phydev, 0x1e, 0x200c); 14000db8189SAndy Fleming if (err < 0) 14100db8189SAndy Fleming return err; 14200db8189SAndy Fleming 14300db8189SAndy Fleming err = phy_write(phydev, 0x1d, 0x5); 14400db8189SAndy Fleming if (err < 0) 14500db8189SAndy Fleming return err; 14600db8189SAndy Fleming 14700db8189SAndy Fleming err = phy_write(phydev, 0x1e, 0); 14800db8189SAndy Fleming if (err < 0) 14900db8189SAndy Fleming return err; 15000db8189SAndy Fleming 15100db8189SAndy Fleming err = phy_write(phydev, 0x1e, 0x100); 15200db8189SAndy Fleming if (err < 0) 15300db8189SAndy Fleming return err; 15400db8189SAndy Fleming 15576884679SAndy Fleming err = phy_write(phydev, MII_M1011_PHY_SCR, 15676884679SAndy Fleming MII_M1011_PHY_SCR_AUTO_CROSS); 15776884679SAndy Fleming if (err < 0) 15876884679SAndy Fleming return err; 15976884679SAndy Fleming 16076884679SAndy Fleming err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL, 16176884679SAndy Fleming MII_M1111_PHY_LED_DIRECT); 16276884679SAndy Fleming if (err < 0) 16376884679SAndy Fleming return err; 16400db8189SAndy Fleming 16500db8189SAndy Fleming err = genphy_config_aneg(phydev); 1668ff44985SAnton Vorontsov if (err < 0) 16700db8189SAndy Fleming return err; 1688ff44985SAnton Vorontsov 1698ff44985SAnton Vorontsov if (phydev->autoneg != AUTONEG_ENABLE) { 1708ff44985SAnton Vorontsov int bmcr; 1718ff44985SAnton Vorontsov 1728ff44985SAnton Vorontsov /* 1738ff44985SAnton Vorontsov * A write to speed/duplex bits (that is performed by 1748ff44985SAnton Vorontsov * genphy_config_aneg() call above) must be followed by 1758ff44985SAnton Vorontsov * a software reset. Otherwise, the write has no effect. 1768ff44985SAnton Vorontsov */ 1778ff44985SAnton Vorontsov bmcr = phy_read(phydev, MII_BMCR); 1788ff44985SAnton Vorontsov if (bmcr < 0) 1798ff44985SAnton Vorontsov return bmcr; 1808ff44985SAnton Vorontsov 1818ff44985SAnton Vorontsov err = phy_write(phydev, MII_BMCR, bmcr | BMCR_RESET); 1828ff44985SAnton Vorontsov if (err < 0) 1838ff44985SAnton Vorontsov return err; 1848ff44985SAnton Vorontsov } 1858ff44985SAnton Vorontsov 1868ff44985SAnton Vorontsov return 0; 18700db8189SAndy Fleming } 18800db8189SAndy Fleming 189140bc929SSergei Poselenov static int m88e1121_config_aneg(struct phy_device *phydev) 190140bc929SSergei Poselenov { 191c477d044SCyril Chemparathy int err, oldpage, mscr; 192c477d044SCyril Chemparathy 193c477d044SCyril Chemparathy oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE); 194c477d044SCyril Chemparathy 195c477d044SCyril Chemparathy err = phy_write(phydev, MII_88E1121_PHY_PAGE, 196c477d044SCyril Chemparathy MII_88E1121_PHY_MSCR_PAGE); 197c477d044SCyril Chemparathy if (err < 0) 198c477d044SCyril Chemparathy return err; 199be8c6480SArnaud Patard 200be8c6480SArnaud Patard if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 201be8c6480SArnaud Patard (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || 202be8c6480SArnaud Patard (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || 203be8c6480SArnaud Patard (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 204be8c6480SArnaud Patard 205c477d044SCyril Chemparathy mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) & 206c477d044SCyril Chemparathy MII_88E1121_PHY_MSCR_DELAY_MASK; 207c477d044SCyril Chemparathy 208c477d044SCyril Chemparathy if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 209c477d044SCyril Chemparathy mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY | 210c477d044SCyril Chemparathy MII_88E1121_PHY_MSCR_TX_DELAY); 211c477d044SCyril Chemparathy else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) 212c477d044SCyril Chemparathy mscr |= MII_88E1121_PHY_MSCR_RX_DELAY; 213c477d044SCyril Chemparathy else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) 214c477d044SCyril Chemparathy mscr |= MII_88E1121_PHY_MSCR_TX_DELAY; 215c477d044SCyril Chemparathy 216c477d044SCyril Chemparathy err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr); 217c477d044SCyril Chemparathy if (err < 0) 218c477d044SCyril Chemparathy return err; 219be8c6480SArnaud Patard } 220c477d044SCyril Chemparathy 221c477d044SCyril Chemparathy phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage); 222140bc929SSergei Poselenov 223140bc929SSergei Poselenov err = phy_write(phydev, MII_BMCR, BMCR_RESET); 224140bc929SSergei Poselenov if (err < 0) 225140bc929SSergei Poselenov return err; 226140bc929SSergei Poselenov 227140bc929SSergei Poselenov err = phy_write(phydev, MII_M1011_PHY_SCR, 228140bc929SSergei Poselenov MII_M1011_PHY_SCR_AUTO_CROSS); 229140bc929SSergei Poselenov if (err < 0) 230140bc929SSergei Poselenov return err; 231140bc929SSergei Poselenov 232c477d044SCyril Chemparathy oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE); 233140bc929SSergei Poselenov 234140bc929SSergei Poselenov phy_write(phydev, MII_88E1121_PHY_PAGE, MII_88E1121_PHY_LED_PAGE); 235140bc929SSergei Poselenov phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF); 236c477d044SCyril Chemparathy phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage); 237140bc929SSergei Poselenov 238140bc929SSergei Poselenov err = genphy_config_aneg(phydev); 239140bc929SSergei Poselenov 240140bc929SSergei Poselenov return err; 241140bc929SSergei Poselenov } 242140bc929SSergei Poselenov 243337ac9d5SCyril Chemparathy static int m88e1318_config_aneg(struct phy_device *phydev) 2443ff1c259SCyril Chemparathy { 2453ff1c259SCyril Chemparathy int err, oldpage, mscr; 2463ff1c259SCyril Chemparathy 2473ff1c259SCyril Chemparathy oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE); 2483ff1c259SCyril Chemparathy 2493ff1c259SCyril Chemparathy err = phy_write(phydev, MII_88E1121_PHY_PAGE, 2503ff1c259SCyril Chemparathy MII_88E1121_PHY_MSCR_PAGE); 2513ff1c259SCyril Chemparathy if (err < 0) 2523ff1c259SCyril Chemparathy return err; 2533ff1c259SCyril Chemparathy 254337ac9d5SCyril Chemparathy mscr = phy_read(phydev, MII_88E1318S_PHY_MSCR1_REG); 255337ac9d5SCyril Chemparathy mscr |= MII_88E1318S_PHY_MSCR1_PAD_ODD; 2563ff1c259SCyril Chemparathy 257337ac9d5SCyril Chemparathy err = phy_write(phydev, MII_88E1318S_PHY_MSCR1_REG, mscr); 2583ff1c259SCyril Chemparathy if (err < 0) 2593ff1c259SCyril Chemparathy return err; 2603ff1c259SCyril Chemparathy 2613ff1c259SCyril Chemparathy err = phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage); 2623ff1c259SCyril Chemparathy if (err < 0) 2633ff1c259SCyril Chemparathy return err; 2643ff1c259SCyril Chemparathy 2653ff1c259SCyril Chemparathy return m88e1121_config_aneg(phydev); 2663ff1c259SCyril Chemparathy } 2673ff1c259SCyril Chemparathy 268895ee682SKim Phillips static int m88e1111_config_init(struct phy_device *phydev) 269895ee682SKim Phillips { 270895ee682SKim Phillips int err; 271be937f1fSAlexandr Smirnov int temp; 272be937f1fSAlexandr Smirnov 273be937f1fSAlexandr Smirnov /* Enable Fiber/Copper auto selection */ 274be937f1fSAlexandr Smirnov temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 2759cf8fa43SWang Jian temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO; 276be937f1fSAlexandr Smirnov phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 277be937f1fSAlexandr Smirnov 278be937f1fSAlexandr Smirnov temp = phy_read(phydev, MII_BMCR); 279be937f1fSAlexandr Smirnov temp |= BMCR_RESET; 280be937f1fSAlexandr Smirnov phy_write(phydev, MII_BMCR, temp); 281895ee682SKim Phillips 282895ee682SKim Phillips if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 2839daf5a76SKim Phillips (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || 2849daf5a76SKim Phillips (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || 2859daf5a76SKim Phillips (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 286895ee682SKim Phillips 287895ee682SKim Phillips temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); 288895ee682SKim Phillips if (temp < 0) 289895ee682SKim Phillips return temp; 290895ee682SKim Phillips 2919daf5a76SKim Phillips if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { 292895ee682SKim Phillips temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); 2939daf5a76SKim Phillips } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 2949daf5a76SKim Phillips temp &= ~MII_M1111_TX_DELAY; 2959daf5a76SKim Phillips temp |= MII_M1111_RX_DELAY; 2969daf5a76SKim Phillips } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 2979daf5a76SKim Phillips temp &= ~MII_M1111_RX_DELAY; 2989daf5a76SKim Phillips temp |= MII_M1111_TX_DELAY; 2999daf5a76SKim Phillips } 300895ee682SKim Phillips 301895ee682SKim Phillips err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); 302895ee682SKim Phillips if (err < 0) 303895ee682SKim Phillips return err; 304895ee682SKim Phillips 305895ee682SKim Phillips temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 306895ee682SKim Phillips if (temp < 0) 307895ee682SKim Phillips return temp; 308895ee682SKim Phillips 309895ee682SKim Phillips temp &= ~(MII_M1111_HWCFG_MODE_MASK); 310be937f1fSAlexandr Smirnov 3117239016dSWang Jian if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES) 312be937f1fSAlexandr Smirnov temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII; 313be937f1fSAlexandr Smirnov else 314be937f1fSAlexandr Smirnov temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII; 315895ee682SKim Phillips 316895ee682SKim Phillips err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 317895ee682SKim Phillips if (err < 0) 318895ee682SKim Phillips return err; 319895ee682SKim Phillips } 320895ee682SKim Phillips 3214117b5beSKapil Juneja if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { 3224117b5beSKapil Juneja temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 3234117b5beSKapil Juneja if (temp < 0) 3244117b5beSKapil Juneja return temp; 3254117b5beSKapil Juneja 3264117b5beSKapil Juneja temp &= ~(MII_M1111_HWCFG_MODE_MASK); 3274117b5beSKapil Juneja temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK; 32832d0c1e1SHaiying Wang temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO; 3294117b5beSKapil Juneja 3304117b5beSKapil Juneja err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 3314117b5beSKapil Juneja if (err < 0) 3324117b5beSKapil Juneja return err; 3334117b5beSKapil Juneja } 3344117b5beSKapil Juneja 3355f8cbc13SLiu Yu-B13201 if (phydev->interface == PHY_INTERFACE_MODE_RTBI) { 3365f8cbc13SLiu Yu-B13201 temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); 3375f8cbc13SLiu Yu-B13201 if (temp < 0) 3385f8cbc13SLiu Yu-B13201 return temp; 3395f8cbc13SLiu Yu-B13201 temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); 3405f8cbc13SLiu Yu-B13201 err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); 3415f8cbc13SLiu Yu-B13201 if (err < 0) 3425f8cbc13SLiu Yu-B13201 return err; 3435f8cbc13SLiu Yu-B13201 3445f8cbc13SLiu Yu-B13201 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 3455f8cbc13SLiu Yu-B13201 if (temp < 0) 3465f8cbc13SLiu Yu-B13201 return temp; 3475f8cbc13SLiu Yu-B13201 temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES); 3485f8cbc13SLiu Yu-B13201 temp |= 0x7 | MII_M1111_HWCFG_FIBER_COPPER_AUTO; 3495f8cbc13SLiu Yu-B13201 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 3505f8cbc13SLiu Yu-B13201 if (err < 0) 3515f8cbc13SLiu Yu-B13201 return err; 3525f8cbc13SLiu Yu-B13201 3535f8cbc13SLiu Yu-B13201 /* soft reset */ 3545f8cbc13SLiu Yu-B13201 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 3555f8cbc13SLiu Yu-B13201 if (err < 0) 3565f8cbc13SLiu Yu-B13201 return err; 3575f8cbc13SLiu Yu-B13201 do 3585f8cbc13SLiu Yu-B13201 temp = phy_read(phydev, MII_BMCR); 3595f8cbc13SLiu Yu-B13201 while (temp & BMCR_RESET); 3605f8cbc13SLiu Yu-B13201 3615f8cbc13SLiu Yu-B13201 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 3625f8cbc13SLiu Yu-B13201 if (temp < 0) 3635f8cbc13SLiu Yu-B13201 return temp; 3645f8cbc13SLiu Yu-B13201 temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES); 3655f8cbc13SLiu Yu-B13201 temp |= MII_M1111_HWCFG_MODE_COPPER_RTBI | MII_M1111_HWCFG_FIBER_COPPER_AUTO; 3665f8cbc13SLiu Yu-B13201 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 3675f8cbc13SLiu Yu-B13201 if (err < 0) 3685f8cbc13SLiu Yu-B13201 return err; 3695f8cbc13SLiu Yu-B13201 } 3705f8cbc13SLiu Yu-B13201 3715f8cbc13SLiu Yu-B13201 372895ee682SKim Phillips err = phy_write(phydev, MII_BMCR, BMCR_RESET); 373895ee682SKim Phillips if (err < 0) 374895ee682SKim Phillips return err; 375895ee682SKim Phillips 376895ee682SKim Phillips return 0; 377895ee682SKim Phillips } 378895ee682SKim Phillips 379605f196eSRon Madrid static int m88e1118_config_aneg(struct phy_device *phydev) 380605f196eSRon Madrid { 381605f196eSRon Madrid int err; 382605f196eSRon Madrid 383605f196eSRon Madrid err = phy_write(phydev, MII_BMCR, BMCR_RESET); 384605f196eSRon Madrid if (err < 0) 385605f196eSRon Madrid return err; 386605f196eSRon Madrid 387605f196eSRon Madrid err = phy_write(phydev, MII_M1011_PHY_SCR, 388605f196eSRon Madrid MII_M1011_PHY_SCR_AUTO_CROSS); 389605f196eSRon Madrid if (err < 0) 390605f196eSRon Madrid return err; 391605f196eSRon Madrid 392605f196eSRon Madrid err = genphy_config_aneg(phydev); 393605f196eSRon Madrid return 0; 394605f196eSRon Madrid } 395605f196eSRon Madrid 396605f196eSRon Madrid static int m88e1118_config_init(struct phy_device *phydev) 397605f196eSRon Madrid { 398605f196eSRon Madrid int err; 399605f196eSRon Madrid 400605f196eSRon Madrid /* Change address */ 401605f196eSRon Madrid err = phy_write(phydev, 0x16, 0x0002); 402605f196eSRon Madrid if (err < 0) 403605f196eSRon Madrid return err; 404605f196eSRon Madrid 405605f196eSRon Madrid /* Enable 1000 Mbit */ 406605f196eSRon Madrid err = phy_write(phydev, 0x15, 0x1070); 407605f196eSRon Madrid if (err < 0) 408605f196eSRon Madrid return err; 409605f196eSRon Madrid 410605f196eSRon Madrid /* Change address */ 411605f196eSRon Madrid err = phy_write(phydev, 0x16, 0x0003); 412605f196eSRon Madrid if (err < 0) 413605f196eSRon Madrid return err; 414605f196eSRon Madrid 415605f196eSRon Madrid /* Adjust LED Control */ 4162f495c39SBenjamin Herrenschmidt if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS) 4172f495c39SBenjamin Herrenschmidt err = phy_write(phydev, 0x10, 0x1100); 4182f495c39SBenjamin Herrenschmidt else 419605f196eSRon Madrid err = phy_write(phydev, 0x10, 0x021e); 420605f196eSRon Madrid if (err < 0) 421605f196eSRon Madrid return err; 422605f196eSRon Madrid 423605f196eSRon Madrid /* Reset address */ 424605f196eSRon Madrid err = phy_write(phydev, 0x16, 0x0); 425605f196eSRon Madrid if (err < 0) 426605f196eSRon Madrid return err; 427605f196eSRon Madrid 428605f196eSRon Madrid err = phy_write(phydev, MII_BMCR, BMCR_RESET); 429605f196eSRon Madrid if (err < 0) 430605f196eSRon Madrid return err; 431605f196eSRon Madrid 432605f196eSRon Madrid return 0; 433605f196eSRon Madrid } 434605f196eSRon Madrid 43576884679SAndy Fleming static int m88e1145_config_init(struct phy_device *phydev) 43676884679SAndy Fleming { 43776884679SAndy Fleming int err; 43876884679SAndy Fleming 43976884679SAndy Fleming /* Take care of errata E0 & E1 */ 44076884679SAndy Fleming err = phy_write(phydev, 0x1d, 0x001b); 44176884679SAndy Fleming if (err < 0) 44276884679SAndy Fleming return err; 44376884679SAndy Fleming 44476884679SAndy Fleming err = phy_write(phydev, 0x1e, 0x418f); 44576884679SAndy Fleming if (err < 0) 44676884679SAndy Fleming return err; 44776884679SAndy Fleming 44876884679SAndy Fleming err = phy_write(phydev, 0x1d, 0x0016); 44976884679SAndy Fleming if (err < 0) 45076884679SAndy Fleming return err; 45176884679SAndy Fleming 45276884679SAndy Fleming err = phy_write(phydev, 0x1e, 0xa2da); 45376884679SAndy Fleming if (err < 0) 45476884679SAndy Fleming return err; 45576884679SAndy Fleming 456895ee682SKim Phillips if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { 45776884679SAndy Fleming int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR); 45876884679SAndy Fleming if (temp < 0) 45976884679SAndy Fleming return temp; 46076884679SAndy Fleming 46176884679SAndy Fleming temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY); 46276884679SAndy Fleming 46376884679SAndy Fleming err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp); 46476884679SAndy Fleming if (err < 0) 46576884679SAndy Fleming return err; 46676884679SAndy Fleming 4672f495c39SBenjamin Herrenschmidt if (phydev->dev_flags & MARVELL_PHY_M1145_FLAGS_RESISTANCE) { 46876884679SAndy Fleming err = phy_write(phydev, 0x1d, 0x0012); 46976884679SAndy Fleming if (err < 0) 47076884679SAndy Fleming return err; 47176884679SAndy Fleming 47276884679SAndy Fleming temp = phy_read(phydev, 0x1e); 47376884679SAndy Fleming if (temp < 0) 47476884679SAndy Fleming return temp; 47576884679SAndy Fleming 47676884679SAndy Fleming temp &= 0xf03f; 47776884679SAndy Fleming temp |= 2 << 9; /* 36 ohm */ 47876884679SAndy Fleming temp |= 2 << 6; /* 39 ohm */ 47976884679SAndy Fleming 48076884679SAndy Fleming err = phy_write(phydev, 0x1e, temp); 48176884679SAndy Fleming if (err < 0) 48276884679SAndy Fleming return err; 48376884679SAndy Fleming 48476884679SAndy Fleming err = phy_write(phydev, 0x1d, 0x3); 48576884679SAndy Fleming if (err < 0) 48676884679SAndy Fleming return err; 48776884679SAndy Fleming 48876884679SAndy Fleming err = phy_write(phydev, 0x1e, 0x8000); 48976884679SAndy Fleming if (err < 0) 49076884679SAndy Fleming return err; 49176884679SAndy Fleming } 49276884679SAndy Fleming } 49376884679SAndy Fleming 49476884679SAndy Fleming return 0; 49576884679SAndy Fleming } 49600db8189SAndy Fleming 497be937f1fSAlexandr Smirnov /* marvell_read_status 498be937f1fSAlexandr Smirnov * 499be937f1fSAlexandr Smirnov * Generic status code does not detect Fiber correctly! 500be937f1fSAlexandr Smirnov * Description: 501be937f1fSAlexandr Smirnov * Check the link, then figure out the current state 502be937f1fSAlexandr Smirnov * by comparing what we advertise with what the link partner 503be937f1fSAlexandr Smirnov * advertises. Start by checking the gigabit possibilities, 504be937f1fSAlexandr Smirnov * then move on to 10/100. 505be937f1fSAlexandr Smirnov */ 506be937f1fSAlexandr Smirnov static int marvell_read_status(struct phy_device *phydev) 507be937f1fSAlexandr Smirnov { 508be937f1fSAlexandr Smirnov int adv; 509be937f1fSAlexandr Smirnov int err; 510be937f1fSAlexandr Smirnov int lpa; 511be937f1fSAlexandr Smirnov int status = 0; 512be937f1fSAlexandr Smirnov 513be937f1fSAlexandr Smirnov /* Update the link, but return if there 514be937f1fSAlexandr Smirnov * was an error */ 515be937f1fSAlexandr Smirnov err = genphy_update_link(phydev); 516be937f1fSAlexandr Smirnov if (err) 517be937f1fSAlexandr Smirnov return err; 518be937f1fSAlexandr Smirnov 519be937f1fSAlexandr Smirnov if (AUTONEG_ENABLE == phydev->autoneg) { 520be937f1fSAlexandr Smirnov status = phy_read(phydev, MII_M1011_PHY_STATUS); 521be937f1fSAlexandr Smirnov if (status < 0) 522be937f1fSAlexandr Smirnov return status; 523be937f1fSAlexandr Smirnov 524be937f1fSAlexandr Smirnov lpa = phy_read(phydev, MII_LPA); 525be937f1fSAlexandr Smirnov if (lpa < 0) 526be937f1fSAlexandr Smirnov return lpa; 527be937f1fSAlexandr Smirnov 528be937f1fSAlexandr Smirnov adv = phy_read(phydev, MII_ADVERTISE); 529be937f1fSAlexandr Smirnov if (adv < 0) 530be937f1fSAlexandr Smirnov return adv; 531be937f1fSAlexandr Smirnov 532be937f1fSAlexandr Smirnov lpa &= adv; 533be937f1fSAlexandr Smirnov 534be937f1fSAlexandr Smirnov if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) 535be937f1fSAlexandr Smirnov phydev->duplex = DUPLEX_FULL; 536be937f1fSAlexandr Smirnov else 537be937f1fSAlexandr Smirnov phydev->duplex = DUPLEX_HALF; 538be937f1fSAlexandr Smirnov 539be937f1fSAlexandr Smirnov status = status & MII_M1011_PHY_STATUS_SPD_MASK; 540be937f1fSAlexandr Smirnov phydev->pause = phydev->asym_pause = 0; 541be937f1fSAlexandr Smirnov 542be937f1fSAlexandr Smirnov switch (status) { 543be937f1fSAlexandr Smirnov case MII_M1011_PHY_STATUS_1000: 544be937f1fSAlexandr Smirnov phydev->speed = SPEED_1000; 545be937f1fSAlexandr Smirnov break; 546be937f1fSAlexandr Smirnov 547be937f1fSAlexandr Smirnov case MII_M1011_PHY_STATUS_100: 548be937f1fSAlexandr Smirnov phydev->speed = SPEED_100; 549be937f1fSAlexandr Smirnov break; 550be937f1fSAlexandr Smirnov 551be937f1fSAlexandr Smirnov default: 552be937f1fSAlexandr Smirnov phydev->speed = SPEED_10; 553be937f1fSAlexandr Smirnov break; 554be937f1fSAlexandr Smirnov } 555be937f1fSAlexandr Smirnov 556be937f1fSAlexandr Smirnov if (phydev->duplex == DUPLEX_FULL) { 557be937f1fSAlexandr Smirnov phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; 558be937f1fSAlexandr Smirnov phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; 559be937f1fSAlexandr Smirnov } 560be937f1fSAlexandr Smirnov } else { 561be937f1fSAlexandr Smirnov int bmcr = phy_read(phydev, MII_BMCR); 562be937f1fSAlexandr Smirnov 563be937f1fSAlexandr Smirnov if (bmcr < 0) 564be937f1fSAlexandr Smirnov return bmcr; 565be937f1fSAlexandr Smirnov 566be937f1fSAlexandr Smirnov if (bmcr & BMCR_FULLDPLX) 567be937f1fSAlexandr Smirnov phydev->duplex = DUPLEX_FULL; 568be937f1fSAlexandr Smirnov else 569be937f1fSAlexandr Smirnov phydev->duplex = DUPLEX_HALF; 570be937f1fSAlexandr Smirnov 571be937f1fSAlexandr Smirnov if (bmcr & BMCR_SPEED1000) 572be937f1fSAlexandr Smirnov phydev->speed = SPEED_1000; 573be937f1fSAlexandr Smirnov else if (bmcr & BMCR_SPEED100) 574be937f1fSAlexandr Smirnov phydev->speed = SPEED_100; 575be937f1fSAlexandr Smirnov else 576be937f1fSAlexandr Smirnov phydev->speed = SPEED_10; 577be937f1fSAlexandr Smirnov 578be937f1fSAlexandr Smirnov phydev->pause = phydev->asym_pause = 0; 579be937f1fSAlexandr Smirnov } 580be937f1fSAlexandr Smirnov 581be937f1fSAlexandr Smirnov return 0; 582be937f1fSAlexandr Smirnov } 583be937f1fSAlexandr Smirnov 584dcd07be3SAnatolij Gustschin static int m88e1121_did_interrupt(struct phy_device *phydev) 585dcd07be3SAnatolij Gustschin { 586dcd07be3SAnatolij Gustschin int imask; 587dcd07be3SAnatolij Gustschin 588dcd07be3SAnatolij Gustschin imask = phy_read(phydev, MII_M1011_IEVENT); 589dcd07be3SAnatolij Gustschin 590dcd07be3SAnatolij Gustschin if (imask & MII_M1011_IMASK_INIT) 591dcd07be3SAnatolij Gustschin return 1; 592dcd07be3SAnatolij Gustschin 593dcd07be3SAnatolij Gustschin return 0; 594dcd07be3SAnatolij Gustschin } 595dcd07be3SAnatolij Gustschin 596e5479239SOlof Johansson static struct phy_driver marvell_drivers[] = { 597e5479239SOlof Johansson { 5982f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1101, 5992f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 60000db8189SAndy Fleming .name = "Marvell 88E1101", 60100db8189SAndy Fleming .features = PHY_GBIT_FEATURES, 60200db8189SAndy Fleming .flags = PHY_HAS_INTERRUPT, 60300db8189SAndy Fleming .config_aneg = &marvell_config_aneg, 60400db8189SAndy Fleming .read_status = &genphy_read_status, 60500db8189SAndy Fleming .ack_interrupt = &marvell_ack_interrupt, 60600db8189SAndy Fleming .config_intr = &marvell_config_intr, 607ac8c635aSOlof Johansson .driver = { .owner = THIS_MODULE }, 608e5479239SOlof Johansson }, 609e5479239SOlof Johansson { 6102f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1112, 6112f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 61285cfb534SOlof Johansson .name = "Marvell 88E1112", 61385cfb534SOlof Johansson .features = PHY_GBIT_FEATURES, 61485cfb534SOlof Johansson .flags = PHY_HAS_INTERRUPT, 61585cfb534SOlof Johansson .config_init = &m88e1111_config_init, 61685cfb534SOlof Johansson .config_aneg = &marvell_config_aneg, 61785cfb534SOlof Johansson .read_status = &genphy_read_status, 61885cfb534SOlof Johansson .ack_interrupt = &marvell_ack_interrupt, 61985cfb534SOlof Johansson .config_intr = &marvell_config_intr, 620ac8c635aSOlof Johansson .driver = { .owner = THIS_MODULE }, 62185cfb534SOlof Johansson }, 62285cfb534SOlof Johansson { 6232f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1111, 6242f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 62576884679SAndy Fleming .name = "Marvell 88E1111", 62676884679SAndy Fleming .features = PHY_GBIT_FEATURES, 62776884679SAndy Fleming .flags = PHY_HAS_INTERRUPT, 628e5479239SOlof Johansson .config_init = &m88e1111_config_init, 62976884679SAndy Fleming .config_aneg = &marvell_config_aneg, 630be937f1fSAlexandr Smirnov .read_status = &marvell_read_status, 63176884679SAndy Fleming .ack_interrupt = &marvell_ack_interrupt, 63276884679SAndy Fleming .config_intr = &marvell_config_intr, 633ac8c635aSOlof Johansson .driver = { .owner = THIS_MODULE }, 634e5479239SOlof Johansson }, 635e5479239SOlof Johansson { 6362f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1118, 6372f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 638605f196eSRon Madrid .name = "Marvell 88E1118", 639605f196eSRon Madrid .features = PHY_GBIT_FEATURES, 640605f196eSRon Madrid .flags = PHY_HAS_INTERRUPT, 641605f196eSRon Madrid .config_init = &m88e1118_config_init, 642605f196eSRon Madrid .config_aneg = &m88e1118_config_aneg, 643605f196eSRon Madrid .read_status = &genphy_read_status, 644605f196eSRon Madrid .ack_interrupt = &marvell_ack_interrupt, 645605f196eSRon Madrid .config_intr = &marvell_config_intr, 646605f196eSRon Madrid .driver = {.owner = THIS_MODULE,}, 647605f196eSRon Madrid }, 648605f196eSRon Madrid { 6492f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1121R, 6502f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 651140bc929SSergei Poselenov .name = "Marvell 88E1121R", 652140bc929SSergei Poselenov .features = PHY_GBIT_FEATURES, 653140bc929SSergei Poselenov .flags = PHY_HAS_INTERRUPT, 654140bc929SSergei Poselenov .config_aneg = &m88e1121_config_aneg, 655140bc929SSergei Poselenov .read_status = &marvell_read_status, 656140bc929SSergei Poselenov .ack_interrupt = &marvell_ack_interrupt, 657140bc929SSergei Poselenov .config_intr = &marvell_config_intr, 658dcd07be3SAnatolij Gustschin .did_interrupt = &m88e1121_did_interrupt, 659140bc929SSergei Poselenov .driver = { .owner = THIS_MODULE }, 660140bc929SSergei Poselenov }, 661140bc929SSergei Poselenov { 662337ac9d5SCyril Chemparathy .phy_id = MARVELL_PHY_ID_88E1318S, 6636ba74014SLinus Torvalds .phy_id_mask = MARVELL_PHY_ID_MASK, 664337ac9d5SCyril Chemparathy .name = "Marvell 88E1318S", 6653ff1c259SCyril Chemparathy .features = PHY_GBIT_FEATURES, 6663ff1c259SCyril Chemparathy .flags = PHY_HAS_INTERRUPT, 667337ac9d5SCyril Chemparathy .config_aneg = &m88e1318_config_aneg, 6683ff1c259SCyril Chemparathy .read_status = &marvell_read_status, 6693ff1c259SCyril Chemparathy .ack_interrupt = &marvell_ack_interrupt, 6703ff1c259SCyril Chemparathy .config_intr = &marvell_config_intr, 6713ff1c259SCyril Chemparathy .did_interrupt = &m88e1121_did_interrupt, 6723ff1c259SCyril Chemparathy .driver = { .owner = THIS_MODULE }, 6733ff1c259SCyril Chemparathy }, 6743ff1c259SCyril Chemparathy { 6752f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1145, 6762f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 67776884679SAndy Fleming .name = "Marvell 88E1145", 67876884679SAndy Fleming .features = PHY_GBIT_FEATURES, 67976884679SAndy Fleming .flags = PHY_HAS_INTERRUPT, 68076884679SAndy Fleming .config_init = &m88e1145_config_init, 68176884679SAndy Fleming .config_aneg = &marvell_config_aneg, 68276884679SAndy Fleming .read_status = &genphy_read_status, 68376884679SAndy Fleming .ack_interrupt = &marvell_ack_interrupt, 68476884679SAndy Fleming .config_intr = &marvell_config_intr, 685ac8c635aSOlof Johansson .driver = { .owner = THIS_MODULE }, 686ac8c635aSOlof Johansson }, 687ac8c635aSOlof Johansson { 6882f495c39SBenjamin Herrenschmidt .phy_id = MARVELL_PHY_ID_88E1240, 6892f495c39SBenjamin Herrenschmidt .phy_id_mask = MARVELL_PHY_ID_MASK, 690ac8c635aSOlof Johansson .name = "Marvell 88E1240", 691ac8c635aSOlof Johansson .features = PHY_GBIT_FEATURES, 692ac8c635aSOlof Johansson .flags = PHY_HAS_INTERRUPT, 693ac8c635aSOlof Johansson .config_init = &m88e1111_config_init, 694ac8c635aSOlof Johansson .config_aneg = &marvell_config_aneg, 695ac8c635aSOlof Johansson .read_status = &genphy_read_status, 696ac8c635aSOlof Johansson .ack_interrupt = &marvell_ack_interrupt, 697ac8c635aSOlof Johansson .config_intr = &marvell_config_intr, 698ac8c635aSOlof Johansson .driver = { .owner = THIS_MODULE }, 699ac8c635aSOlof Johansson }, 70076884679SAndy Fleming }; 70176884679SAndy Fleming 70200db8189SAndy Fleming static int __init marvell_init(void) 70300db8189SAndy Fleming { 70476884679SAndy Fleming int ret; 705e5479239SOlof Johansson int i; 70676884679SAndy Fleming 707e5479239SOlof Johansson for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) { 708e5479239SOlof Johansson ret = phy_driver_register(&marvell_drivers[i]); 709e5479239SOlof Johansson 710e5479239SOlof Johansson if (ret) { 711e5479239SOlof Johansson while (i-- > 0) 712e5479239SOlof Johansson phy_driver_unregister(&marvell_drivers[i]); 71376884679SAndy Fleming return ret; 714e5479239SOlof Johansson } 715e5479239SOlof Johansson } 71676884679SAndy Fleming 71776884679SAndy Fleming return 0; 71800db8189SAndy Fleming } 71900db8189SAndy Fleming 72000db8189SAndy Fleming static void __exit marvell_exit(void) 72100db8189SAndy Fleming { 722e5479239SOlof Johansson int i; 723e5479239SOlof Johansson 724e5479239SOlof Johansson for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) 725e5479239SOlof Johansson phy_driver_unregister(&marvell_drivers[i]); 72600db8189SAndy Fleming } 72700db8189SAndy Fleming 72800db8189SAndy Fleming module_init(marvell_init); 72900db8189SAndy Fleming module_exit(marvell_exit); 7304e4f10f6SDavid Woodhouse 731cf93c945SUwe Kleine-König static struct mdio_device_id __maybe_unused marvell_tbl[] = { 7324e4f10f6SDavid Woodhouse { 0x01410c60, 0xfffffff0 }, 7334e4f10f6SDavid Woodhouse { 0x01410c90, 0xfffffff0 }, 7344e4f10f6SDavid Woodhouse { 0x01410cc0, 0xfffffff0 }, 7354e4f10f6SDavid Woodhouse { 0x01410e10, 0xfffffff0 }, 7364e4f10f6SDavid Woodhouse { 0x01410cb0, 0xfffffff0 }, 7374e4f10f6SDavid Woodhouse { 0x01410cd0, 0xfffffff0 }, 7384e4f10f6SDavid Woodhouse { 0x01410e30, 0xfffffff0 }, 7393ff1c259SCyril Chemparathy { 0x01410e90, 0xfffffff0 }, 7404e4f10f6SDavid Woodhouse { } 7414e4f10f6SDavid Woodhouse }; 7424e4f10f6SDavid Woodhouse 7434e4f10f6SDavid Woodhouse MODULE_DEVICE_TABLE(mdio, marvell_tbl); 744