1b560a58cSFlorian Fainelli /* 2b560a58cSFlorian Fainelli * Broadcom BCM7xxx internal transceivers support. 3b560a58cSFlorian Fainelli * 4b560a58cSFlorian Fainelli * Copyright (C) 2014, Broadcom Corporation 5b560a58cSFlorian Fainelli * 6b560a58cSFlorian Fainelli * This program is free software; you can redistribute it and/or 7b560a58cSFlorian Fainelli * modify it under the terms of the GNU General Public License 8b560a58cSFlorian Fainelli * as published by the Free Software Foundation; either version 9b560a58cSFlorian Fainelli * 2 of the License, or (at your option) any later version. 10b560a58cSFlorian Fainelli */ 11b560a58cSFlorian Fainelli 12b560a58cSFlorian Fainelli #include <linux/module.h> 13b560a58cSFlorian Fainelli #include <linux/phy.h> 14b560a58cSFlorian Fainelli #include <linux/delay.h> 15b560a58cSFlorian Fainelli #include <linux/bitops.h> 16b560a58cSFlorian Fainelli #include <linux/brcmphy.h> 17b560a58cSFlorian Fainelli 18b560a58cSFlorian Fainelli /* Broadcom BCM7xxx internal PHY registers */ 19b560a58cSFlorian Fainelli #define MII_BCM7XXX_CHANNEL_WIDTH 0x2000 20b560a58cSFlorian Fainelli 21b560a58cSFlorian Fainelli /* 40nm only register definitions */ 22b560a58cSFlorian Fainelli #define MII_BCM7XXX_100TX_AUX_CTL 0x10 23b560a58cSFlorian Fainelli #define MII_BCM7XXX_100TX_FALSE_CAR 0x13 24b560a58cSFlorian Fainelli #define MII_BCM7XXX_100TX_DISC 0x14 25b560a58cSFlorian Fainelli #define MII_BCM7XXX_AUX_MODE 0x1d 26b560a58cSFlorian Fainelli #define MII_BCM7XX_64CLK_MDIO BIT(12) 27b560a58cSFlorian Fainelli #define MII_BCM7XXX_CORE_BASE1E 0x1e 28b560a58cSFlorian Fainelli #define MII_BCM7XXX_TEST 0x1f 29b560a58cSFlorian Fainelli #define MII_BCM7XXX_SHD_MODE_2 BIT(2) 30b560a58cSFlorian Fainelli 31a3622f2cSFlorian Fainelli /* 28nm only register definitions */ 32a3622f2cSFlorian Fainelli #define MISC_ADDR(base, channel) base, channel 33a3622f2cSFlorian Fainelli 34a3622f2cSFlorian Fainelli #define DSP_TAP10 MISC_ADDR(0x0a, 0) 35a3622f2cSFlorian Fainelli #define PLL_PLLCTRL_1 MISC_ADDR(0x32, 1) 36a3622f2cSFlorian Fainelli #define PLL_PLLCTRL_2 MISC_ADDR(0x32, 2) 37a3622f2cSFlorian Fainelli #define PLL_PLLCTRL_4 MISC_ADDR(0x33, 0) 38a3622f2cSFlorian Fainelli 39a3622f2cSFlorian Fainelli #define AFE_RXCONFIG_0 MISC_ADDR(0x38, 0) 40a3622f2cSFlorian Fainelli #define AFE_RXCONFIG_1 MISC_ADDR(0x38, 1) 41a3622f2cSFlorian Fainelli #define AFE_RX_LP_COUNTER MISC_ADDR(0x38, 3) 42a3622f2cSFlorian Fainelli #define AFE_TX_CONFIG MISC_ADDR(0x39, 0) 43a3622f2cSFlorian Fainelli #define AFE_HPF_TRIM_OTHERS MISC_ADDR(0x3a, 0) 44a3622f2cSFlorian Fainelli 45a3622f2cSFlorian Fainelli #define CORE_EXPB0 0xb0 46a3622f2cSFlorian Fainelli 47b560a58cSFlorian Fainelli static int bcm7445_config_init(struct phy_device *phydev) 48b560a58cSFlorian Fainelli { 49b560a58cSFlorian Fainelli int ret; 50b560a58cSFlorian Fainelli const struct bcm7445_regs { 51b560a58cSFlorian Fainelli int reg; 52b560a58cSFlorian Fainelli u16 value; 53b560a58cSFlorian Fainelli } bcm7445_regs_cfg[] = { 54b560a58cSFlorian Fainelli /* increases ADC latency by 24ns */ 55b560a58cSFlorian Fainelli { MII_BCM54XX_EXP_SEL, 0x0038 }, 56b560a58cSFlorian Fainelli { MII_BCM54XX_EXP_DATA, 0xAB95 }, 57b560a58cSFlorian Fainelli /* increases internal 1V LDO voltage by 5% */ 58b560a58cSFlorian Fainelli { MII_BCM54XX_EXP_SEL, 0x2038 }, 59b560a58cSFlorian Fainelli { MII_BCM54XX_EXP_DATA, 0xBB22 }, 60b560a58cSFlorian Fainelli /* reduce RX low pass filter corner frequency */ 61b560a58cSFlorian Fainelli { MII_BCM54XX_EXP_SEL, 0x6038 }, 62b560a58cSFlorian Fainelli { MII_BCM54XX_EXP_DATA, 0xFFC5 }, 63b560a58cSFlorian Fainelli /* reduce RX high pass filter corner frequency */ 64b560a58cSFlorian Fainelli { MII_BCM54XX_EXP_SEL, 0x003a }, 65b560a58cSFlorian Fainelli { MII_BCM54XX_EXP_DATA, 0x2002 }, 66b560a58cSFlorian Fainelli }; 67b560a58cSFlorian Fainelli unsigned int i; 68b560a58cSFlorian Fainelli 69b560a58cSFlorian Fainelli for (i = 0; i < ARRAY_SIZE(bcm7445_regs_cfg); i++) { 70b560a58cSFlorian Fainelli ret = phy_write(phydev, 71b560a58cSFlorian Fainelli bcm7445_regs_cfg[i].reg, 72b560a58cSFlorian Fainelli bcm7445_regs_cfg[i].value); 73b560a58cSFlorian Fainelli if (ret) 74b560a58cSFlorian Fainelli return ret; 75b560a58cSFlorian Fainelli } 76b560a58cSFlorian Fainelli 77b560a58cSFlorian Fainelli return 0; 78b560a58cSFlorian Fainelli } 79b560a58cSFlorian Fainelli 80b560a58cSFlorian Fainelli static void phy_write_exp(struct phy_device *phydev, 81b560a58cSFlorian Fainelli u16 reg, u16 value) 82b560a58cSFlorian Fainelli { 83b560a58cSFlorian Fainelli phy_write(phydev, MII_BCM54XX_EXP_SEL, MII_BCM54XX_EXP_SEL_ER | reg); 84b560a58cSFlorian Fainelli phy_write(phydev, MII_BCM54XX_EXP_DATA, value); 85b560a58cSFlorian Fainelli } 86b560a58cSFlorian Fainelli 87b560a58cSFlorian Fainelli static void phy_write_misc(struct phy_device *phydev, 88b560a58cSFlorian Fainelli u16 reg, u16 chl, u16 value) 89b560a58cSFlorian Fainelli { 90b560a58cSFlorian Fainelli int tmp; 91b560a58cSFlorian Fainelli 92b560a58cSFlorian Fainelli phy_write(phydev, MII_BCM54XX_AUX_CTL, MII_BCM54XX_AUXCTL_SHDWSEL_MISC); 93b560a58cSFlorian Fainelli 94b560a58cSFlorian Fainelli tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL); 95b560a58cSFlorian Fainelli tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA; 96b560a58cSFlorian Fainelli phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp); 97b560a58cSFlorian Fainelli 98b560a58cSFlorian Fainelli tmp = (chl * MII_BCM7XXX_CHANNEL_WIDTH) | reg; 99b560a58cSFlorian Fainelli phy_write(phydev, MII_BCM54XX_EXP_SEL, tmp); 100b560a58cSFlorian Fainelli 101b560a58cSFlorian Fainelli phy_write(phydev, MII_BCM54XX_EXP_DATA, value); 102b560a58cSFlorian Fainelli } 103b560a58cSFlorian Fainelli 104b560a58cSFlorian Fainelli static int bcm7xxx_28nm_afe_config_init(struct phy_device *phydev) 105b560a58cSFlorian Fainelli { 106b560a58cSFlorian Fainelli /* write AFE_RXCONFIG_0 */ 107a3622f2cSFlorian Fainelli phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19); 108b560a58cSFlorian Fainelli 109b560a58cSFlorian Fainelli /* write AFE_RXCONFIG_1 */ 110a3622f2cSFlorian Fainelli phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f); 111b560a58cSFlorian Fainelli 112b560a58cSFlorian Fainelli /* write AFE_RX_LP_COUNTER */ 113a3622f2cSFlorian Fainelli phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc7); 114b560a58cSFlorian Fainelli 115b560a58cSFlorian Fainelli /* write AFE_HPF_TRIM_OTHERS */ 116a3622f2cSFlorian Fainelli phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b); 117b560a58cSFlorian Fainelli 118b560a58cSFlorian Fainelli /* write AFTE_TX_CONFIG */ 119a3622f2cSFlorian Fainelli phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800); 120b560a58cSFlorian Fainelli 121b560a58cSFlorian Fainelli /* Increase VCO range to prevent unlocking problem of PLL at low 122b560a58cSFlorian Fainelli * temp 123b560a58cSFlorian Fainelli */ 124a3622f2cSFlorian Fainelli phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048); 125b560a58cSFlorian Fainelli 126b560a58cSFlorian Fainelli /* Change Ki to 011 */ 127a3622f2cSFlorian Fainelli phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b); 128b560a58cSFlorian Fainelli 129b560a58cSFlorian Fainelli /* Disable loading of TVCO buffer to bandgap, set bandgap trim 130b560a58cSFlorian Fainelli * to 111 131b560a58cSFlorian Fainelli */ 132a3622f2cSFlorian Fainelli phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20); 133b560a58cSFlorian Fainelli 134b560a58cSFlorian Fainelli /* Adjust bias current trim by -3 */ 135a3622f2cSFlorian Fainelli phy_write_misc(phydev, DSP_TAP10, 0x690b); 136b560a58cSFlorian Fainelli 137b560a58cSFlorian Fainelli /* Switch to CORE_BASE1E */ 138b560a58cSFlorian Fainelli phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0xd); 139b560a58cSFlorian Fainelli 140b560a58cSFlorian Fainelli /* Reset R_CAL/RC_CAL Engine */ 141a3622f2cSFlorian Fainelli phy_write_exp(phydev, CORE_EXPB0, 0x0010); 142b560a58cSFlorian Fainelli 143b560a58cSFlorian Fainelli /* Disable Reset R_CAL/RC_CAL Engine */ 144a3622f2cSFlorian Fainelli phy_write_exp(phydev, CORE_EXPB0, 0x0000); 145b560a58cSFlorian Fainelli 146b560a58cSFlorian Fainelli return 0; 147b560a58cSFlorian Fainelli } 148b560a58cSFlorian Fainelli 149b560a58cSFlorian Fainelli static int bcm7xxx_28nm_config_init(struct phy_device *phydev) 150b560a58cSFlorian Fainelli { 151b560a58cSFlorian Fainelli int ret; 152b560a58cSFlorian Fainelli 153b560a58cSFlorian Fainelli ret = bcm7445_config_init(phydev); 154b560a58cSFlorian Fainelli if (ret) 155b560a58cSFlorian Fainelli return ret; 156b560a58cSFlorian Fainelli 157b560a58cSFlorian Fainelli return bcm7xxx_28nm_afe_config_init(phydev); 158b560a58cSFlorian Fainelli } 159b560a58cSFlorian Fainelli 160b560a58cSFlorian Fainelli static int phy_set_clr_bits(struct phy_device *dev, int location, 161b560a58cSFlorian Fainelli int set_mask, int clr_mask) 162b560a58cSFlorian Fainelli { 163b560a58cSFlorian Fainelli int v, ret; 164b560a58cSFlorian Fainelli 165b560a58cSFlorian Fainelli v = phy_read(dev, location); 166b560a58cSFlorian Fainelli if (v < 0) 167b560a58cSFlorian Fainelli return v; 168b560a58cSFlorian Fainelli 169b560a58cSFlorian Fainelli v &= ~clr_mask; 170b560a58cSFlorian Fainelli v |= set_mask; 171b560a58cSFlorian Fainelli 172b560a58cSFlorian Fainelli ret = phy_write(dev, location, v); 173b560a58cSFlorian Fainelli if (ret < 0) 174b560a58cSFlorian Fainelli return ret; 175b560a58cSFlorian Fainelli 176b560a58cSFlorian Fainelli return v; 177b560a58cSFlorian Fainelli } 178b560a58cSFlorian Fainelli 179b560a58cSFlorian Fainelli static int bcm7xxx_config_init(struct phy_device *phydev) 180b560a58cSFlorian Fainelli { 181b560a58cSFlorian Fainelli int ret; 182b560a58cSFlorian Fainelli 183b560a58cSFlorian Fainelli /* Enable 64 clock MDIO */ 184b560a58cSFlorian Fainelli phy_write(phydev, MII_BCM7XXX_AUX_MODE, MII_BCM7XX_64CLK_MDIO); 185b560a58cSFlorian Fainelli phy_read(phydev, MII_BCM7XXX_AUX_MODE); 186b560a58cSFlorian Fainelli 187b560a58cSFlorian Fainelli /* Workaround only required for 100Mbits/sec */ 188b560a58cSFlorian Fainelli if (!(phydev->dev_flags & PHY_BRCM_100MBPS_WAR)) 189b560a58cSFlorian Fainelli return 0; 190b560a58cSFlorian Fainelli 191b560a58cSFlorian Fainelli /* set shadow mode 2 */ 192b560a58cSFlorian Fainelli ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 193b560a58cSFlorian Fainelli MII_BCM7XXX_SHD_MODE_2, MII_BCM7XXX_SHD_MODE_2); 194b560a58cSFlorian Fainelli if (ret < 0) 195b560a58cSFlorian Fainelli return ret; 196b560a58cSFlorian Fainelli 197b560a58cSFlorian Fainelli /* set iddq_clkbias */ 198b560a58cSFlorian Fainelli phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0F00); 199b560a58cSFlorian Fainelli udelay(10); 200b560a58cSFlorian Fainelli 201b560a58cSFlorian Fainelli /* reset iddq_clkbias */ 202b560a58cSFlorian Fainelli phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0C00); 203b560a58cSFlorian Fainelli 204b560a58cSFlorian Fainelli phy_write(phydev, MII_BCM7XXX_100TX_FALSE_CAR, 0x7555); 205b560a58cSFlorian Fainelli 206b560a58cSFlorian Fainelli /* reset shadow mode 2 */ 207b560a58cSFlorian Fainelli ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, MII_BCM7XXX_SHD_MODE_2, 0); 208b560a58cSFlorian Fainelli if (ret < 0) 209b560a58cSFlorian Fainelli return ret; 210b560a58cSFlorian Fainelli 211b560a58cSFlorian Fainelli return 0; 212b560a58cSFlorian Fainelli } 213b560a58cSFlorian Fainelli 214b560a58cSFlorian Fainelli /* Workaround for putting the PHY in IDDQ mode, required 215b560a58cSFlorian Fainelli * for all BCM7XXX PHYs 216b560a58cSFlorian Fainelli */ 217b560a58cSFlorian Fainelli static int bcm7xxx_suspend(struct phy_device *phydev) 218b560a58cSFlorian Fainelli { 219b560a58cSFlorian Fainelli int ret; 220b560a58cSFlorian Fainelli const struct bcm7xxx_regs { 221b560a58cSFlorian Fainelli int reg; 222b560a58cSFlorian Fainelli u16 value; 223b560a58cSFlorian Fainelli } bcm7xxx_suspend_cfg[] = { 224b560a58cSFlorian Fainelli { MII_BCM7XXX_TEST, 0x008b }, 225b560a58cSFlorian Fainelli { MII_BCM7XXX_100TX_AUX_CTL, 0x01c0 }, 226b560a58cSFlorian Fainelli { MII_BCM7XXX_100TX_DISC, 0x7000 }, 227b560a58cSFlorian Fainelli { MII_BCM7XXX_TEST, 0x000f }, 228b560a58cSFlorian Fainelli { MII_BCM7XXX_100TX_AUX_CTL, 0x20d0 }, 229b560a58cSFlorian Fainelli { MII_BCM7XXX_TEST, 0x000b }, 230b560a58cSFlorian Fainelli }; 231b560a58cSFlorian Fainelli unsigned int i; 232b560a58cSFlorian Fainelli 233b560a58cSFlorian Fainelli for (i = 0; i < ARRAY_SIZE(bcm7xxx_suspend_cfg); i++) { 234b560a58cSFlorian Fainelli ret = phy_write(phydev, 235b560a58cSFlorian Fainelli bcm7xxx_suspend_cfg[i].reg, 236b560a58cSFlorian Fainelli bcm7xxx_suspend_cfg[i].value); 237b560a58cSFlorian Fainelli if (ret) 238b560a58cSFlorian Fainelli return ret; 239b560a58cSFlorian Fainelli } 240b560a58cSFlorian Fainelli 241b560a58cSFlorian Fainelli return 0; 242b560a58cSFlorian Fainelli } 243b560a58cSFlorian Fainelli 244b560a58cSFlorian Fainelli static int bcm7xxx_dummy_config_init(struct phy_device *phydev) 245b560a58cSFlorian Fainelli { 246b560a58cSFlorian Fainelli return 0; 247b560a58cSFlorian Fainelli } 248b560a58cSFlorian Fainelli 249b560a58cSFlorian Fainelli static struct phy_driver bcm7xxx_driver[] = { 250b560a58cSFlorian Fainelli { 251b560a58cSFlorian Fainelli .phy_id = PHY_ID_BCM7366, 252b560a58cSFlorian Fainelli .phy_id_mask = 0xfffffff0, 253b560a58cSFlorian Fainelli .name = "Broadcom BCM7366", 254b560a58cSFlorian Fainelli .features = PHY_GBIT_FEATURES | 255b560a58cSFlorian Fainelli SUPPORTED_Pause | SUPPORTED_Asym_Pause, 256b560a58cSFlorian Fainelli .flags = PHY_IS_INTERNAL, 257b560a58cSFlorian Fainelli .config_init = bcm7xxx_28nm_afe_config_init, 258b560a58cSFlorian Fainelli .config_aneg = genphy_config_aneg, 259b560a58cSFlorian Fainelli .read_status = genphy_read_status, 260b560a58cSFlorian Fainelli .suspend = bcm7xxx_suspend, 261b560a58cSFlorian Fainelli .resume = bcm7xxx_28nm_afe_config_init, 262b560a58cSFlorian Fainelli .driver = { .owner = THIS_MODULE }, 263b560a58cSFlorian Fainelli }, { 264b560a58cSFlorian Fainelli .phy_id = PHY_ID_BCM7439, 265b560a58cSFlorian Fainelli .phy_id_mask = 0xfffffff0, 266b560a58cSFlorian Fainelli .name = "Broadcom BCM7439", 267b560a58cSFlorian Fainelli .features = PHY_GBIT_FEATURES | 268b560a58cSFlorian Fainelli SUPPORTED_Pause | SUPPORTED_Asym_Pause, 269b560a58cSFlorian Fainelli .flags = PHY_IS_INTERNAL, 270b560a58cSFlorian Fainelli .config_init = bcm7xxx_28nm_afe_config_init, 271b560a58cSFlorian Fainelli .config_aneg = genphy_config_aneg, 272b560a58cSFlorian Fainelli .read_status = genphy_read_status, 273b560a58cSFlorian Fainelli .suspend = bcm7xxx_suspend, 274b560a58cSFlorian Fainelli .resume = bcm7xxx_28nm_afe_config_init, 275b560a58cSFlorian Fainelli .driver = { .owner = THIS_MODULE }, 276b560a58cSFlorian Fainelli }, { 277b560a58cSFlorian Fainelli .phy_id = PHY_ID_BCM7445, 278b560a58cSFlorian Fainelli .phy_id_mask = 0xfffffff0, 279b560a58cSFlorian Fainelli .name = "Broadcom BCM7445", 280b560a58cSFlorian Fainelli .features = PHY_GBIT_FEATURES | 281b560a58cSFlorian Fainelli SUPPORTED_Pause | SUPPORTED_Asym_Pause, 282b560a58cSFlorian Fainelli .flags = PHY_IS_INTERNAL, 283b560a58cSFlorian Fainelli .config_init = bcm7xxx_28nm_config_init, 284b560a58cSFlorian Fainelli .config_aneg = genphy_config_aneg, 285b560a58cSFlorian Fainelli .read_status = genphy_read_status, 286b560a58cSFlorian Fainelli .suspend = bcm7xxx_suspend, 287b560a58cSFlorian Fainelli .resume = bcm7xxx_28nm_config_init, 288b560a58cSFlorian Fainelli .driver = { .owner = THIS_MODULE }, 289b560a58cSFlorian Fainelli }, { 290b560a58cSFlorian Fainelli .name = "Broadcom BCM7XXX 28nm", 291b560a58cSFlorian Fainelli .phy_id = PHY_ID_BCM7XXX_28, 292b560a58cSFlorian Fainelli .phy_id_mask = PHY_BCM_OUI_MASK, 293b560a58cSFlorian Fainelli .features = PHY_GBIT_FEATURES | 294b560a58cSFlorian Fainelli SUPPORTED_Pause | SUPPORTED_Asym_Pause, 295b560a58cSFlorian Fainelli .flags = PHY_IS_INTERNAL, 296b560a58cSFlorian Fainelli .config_init = bcm7xxx_28nm_config_init, 297b560a58cSFlorian Fainelli .config_aneg = genphy_config_aneg, 298b560a58cSFlorian Fainelli .read_status = genphy_read_status, 299b560a58cSFlorian Fainelli .suspend = bcm7xxx_suspend, 300b560a58cSFlorian Fainelli .resume = bcm7xxx_28nm_config_init, 301b560a58cSFlorian Fainelli .driver = { .owner = THIS_MODULE }, 302b560a58cSFlorian Fainelli }, { 303b560a58cSFlorian Fainelli .phy_id = PHY_BCM_OUI_4, 304b560a58cSFlorian Fainelli .phy_id_mask = 0xffff0000, 305b560a58cSFlorian Fainelli .name = "Broadcom BCM7XXX 40nm", 306b560a58cSFlorian Fainelli .features = PHY_GBIT_FEATURES | 307b560a58cSFlorian Fainelli SUPPORTED_Pause | SUPPORTED_Asym_Pause, 308b560a58cSFlorian Fainelli .flags = PHY_IS_INTERNAL, 309b560a58cSFlorian Fainelli .config_init = bcm7xxx_config_init, 310b560a58cSFlorian Fainelli .config_aneg = genphy_config_aneg, 311b560a58cSFlorian Fainelli .read_status = genphy_read_status, 312b560a58cSFlorian Fainelli .suspend = bcm7xxx_suspend, 313b560a58cSFlorian Fainelli .resume = bcm7xxx_config_init, 314b560a58cSFlorian Fainelli .driver = { .owner = THIS_MODULE }, 315b560a58cSFlorian Fainelli }, { 316b560a58cSFlorian Fainelli .phy_id = PHY_BCM_OUI_5, 317b560a58cSFlorian Fainelli .phy_id_mask = 0xffffff00, 318b560a58cSFlorian Fainelli .name = "Broadcom BCM7XXX 65nm", 319b560a58cSFlorian Fainelli .features = PHY_BASIC_FEATURES | 320b560a58cSFlorian Fainelli SUPPORTED_Pause | SUPPORTED_Asym_Pause, 321b560a58cSFlorian Fainelli .flags = PHY_IS_INTERNAL, 322b560a58cSFlorian Fainelli .config_init = bcm7xxx_dummy_config_init, 323b560a58cSFlorian Fainelli .config_aneg = genphy_config_aneg, 324b560a58cSFlorian Fainelli .read_status = genphy_read_status, 325b560a58cSFlorian Fainelli .suspend = bcm7xxx_suspend, 326b560a58cSFlorian Fainelli .resume = bcm7xxx_config_init, 327b560a58cSFlorian Fainelli .driver = { .owner = THIS_MODULE }, 328b560a58cSFlorian Fainelli } }; 329b560a58cSFlorian Fainelli 330b560a58cSFlorian Fainelli static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { 331b560a58cSFlorian Fainelli { PHY_ID_BCM7366, 0xfffffff0, }, 332b560a58cSFlorian Fainelli { PHY_ID_BCM7439, 0xfffffff0, }, 333b560a58cSFlorian Fainelli { PHY_ID_BCM7445, 0xfffffff0, }, 334b560a58cSFlorian Fainelli { PHY_ID_BCM7XXX_28, 0xfffffc00 }, 335b560a58cSFlorian Fainelli { PHY_BCM_OUI_4, 0xffff0000 }, 336b560a58cSFlorian Fainelli { PHY_BCM_OUI_5, 0xffffff00 }, 337b560a58cSFlorian Fainelli { } 338b560a58cSFlorian Fainelli }; 339b560a58cSFlorian Fainelli 340b560a58cSFlorian Fainelli static int __init bcm7xxx_phy_init(void) 341b560a58cSFlorian Fainelli { 342b560a58cSFlorian Fainelli return phy_drivers_register(bcm7xxx_driver, 343b560a58cSFlorian Fainelli ARRAY_SIZE(bcm7xxx_driver)); 344b560a58cSFlorian Fainelli } 345b560a58cSFlorian Fainelli 346b560a58cSFlorian Fainelli static void __exit bcm7xxx_phy_exit(void) 347b560a58cSFlorian Fainelli { 348b560a58cSFlorian Fainelli phy_drivers_unregister(bcm7xxx_driver, 349b560a58cSFlorian Fainelli ARRAY_SIZE(bcm7xxx_driver)); 350b560a58cSFlorian Fainelli } 351b560a58cSFlorian Fainelli 352b560a58cSFlorian Fainelli module_init(bcm7xxx_phy_init); 353b560a58cSFlorian Fainelli module_exit(bcm7xxx_phy_exit); 354b560a58cSFlorian Fainelli 355b560a58cSFlorian Fainelli MODULE_DEVICE_TABLE(mdio, bcm7xxx_tbl); 356b560a58cSFlorian Fainelli 357b560a58cSFlorian Fainelli MODULE_DESCRIPTION("Broadcom BCM7xxx internal PHY driver"); 358b560a58cSFlorian Fainelli MODULE_LICENSE("GPL"); 359b560a58cSFlorian Fainelli MODULE_AUTHOR("Broadcom Corporation"); 360