linux/drivers/net/phy/broadcom.c
<<
>>
Prefs
   1/*
   2 *      drivers/net/phy/broadcom.c
   3 *
   4 *      Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet
   5 *      transceivers.
   6 *
   7 *      Copyright (c) 2006  Maciej W. Rozycki
   8 *
   9 *      Inspired by code written by Amy Fong.
  10 *
  11 *      This program is free software; you can redistribute it and/or
  12 *      modify it under the terms of the GNU General Public License
  13 *      as published by the Free Software Foundation; either version
  14 *      2 of the License, or (at your option) any later version.
  15 */
  16
  17#include <linux/module.h>
  18#include <linux/phy.h>
  19#include <linux/brcmphy.h>
  20
  21
  22#define BRCM_PHY_MODEL(phydev) \
  23        ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
  24
  25#define BRCM_PHY_REV(phydev) \
  26        ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
  27
  28MODULE_DESCRIPTION("Broadcom PHY driver");
  29MODULE_AUTHOR("Maciej W. Rozycki");
  30MODULE_LICENSE("GPL");
  31
  32/* Indirect register access functions for the Expansion Registers */
  33static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum)
  34{
  35        int val;
  36
  37        val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
  38        if (val < 0)
  39                return val;
  40
  41        val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
  42
  43        /* Restore default value.  It's O.K. if this write fails. */
  44        phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
  45
  46        return val;
  47}
  48
  49static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val)
  50{
  51        int ret;
  52
  53        ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
  54        if (ret < 0)
  55                return ret;
  56
  57        ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
  58
  59        /* Restore default value.  It's O.K. if this write fails. */
  60        phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
  61
  62        return ret;
  63}
  64
  65static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
  66{
  67        return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
  68}
  69
  70/* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
  71static int bcm50610_a0_workaround(struct phy_device *phydev)
  72{
  73        int err;
  74
  75        err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
  76                                MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
  77                                MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
  78        if (err < 0)
  79                return err;
  80
  81        err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
  82                                        MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
  83        if (err < 0)
  84                return err;
  85
  86        err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
  87                                MII_BCM54XX_EXP_EXP75_VDACCTRL);
  88        if (err < 0)
  89                return err;
  90
  91        err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
  92                                MII_BCM54XX_EXP_EXP96_MYST);
  93        if (err < 0)
  94                return err;
  95
  96        err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
  97                                MII_BCM54XX_EXP_EXP97_MYST);
  98
  99        return err;
 100}
 101
 102static int bcm54xx_phydsp_config(struct phy_device *phydev)
 103{
 104        int err, err2;
 105
 106        /* Enable the SMDSP clock */
 107        err = bcm54xx_auxctl_write(phydev,
 108                                   MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
 109                                   MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
 110                                   MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
 111        if (err < 0)
 112                return err;
 113
 114        if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
 115            BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
 116                /* Clear bit 9 to fix a phy interop issue. */
 117                err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
 118                                        MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
 119                if (err < 0)
 120                        goto error;
 121
 122                if (phydev->drv->phy_id == PHY_ID_BCM50610) {
 123                        err = bcm50610_a0_workaround(phydev);
 124                        if (err < 0)
 125                                goto error;
 126                }
 127        }
 128
 129        if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
 130                int val;
 131
 132                val = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75);
 133                if (val < 0)
 134                        goto error;
 135
 136                val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
 137                err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, val);
 138        }
 139
 140error:
 141        /* Disable the SMDSP clock */
 142        err2 = bcm54xx_auxctl_write(phydev,
 143                                    MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
 144                                    MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
 145
 146        /* Return the first error reported. */
 147        return err ? err : err2;
 148}
 149
 150static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
 151{
 152        u32 orig;
 153        int val;
 154        bool clk125en = true;
 155
 156        /* Abort if we are using an untested phy. */
 157        if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&
 158            BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&
 159            BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
 160                return;
 161
 162        val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
 163        if (val < 0)
 164                return;
 165
 166        orig = val;
 167
 168        if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
 169             BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
 170            BRCM_PHY_REV(phydev) >= 0x3) {
 171                /*
 172                 * Here, bit 0 _disables_ CLK125 when set.
 173                 * This bit is set by default.
 174                 */
 175                clk125en = false;
 176        } else {
 177                if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
 178                        /* Here, bit 0 _enables_ CLK125 when set */
 179                        val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
 180                        clk125en = false;
 181                }
 182        }
 183
 184        if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
 185                val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
 186        else
 187                val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
 188
 189        if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY)
 190                val |= BCM54XX_SHD_SCR3_TRDDAPD;
 191
 192        if (orig != val)
 193                bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
 194
 195        val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
 196        if (val < 0)
 197                return;
 198
 199        orig = val;
 200
 201        if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
 202                val |= BCM54XX_SHD_APD_EN;
 203        else
 204                val &= ~BCM54XX_SHD_APD_EN;
 205
 206        if (orig != val)
 207                bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
 208}
 209
 210static int bcm54xx_config_init(struct phy_device *phydev)
 211{
 212        int reg, err;
 213
 214        reg = phy_read(phydev, MII_BCM54XX_ECR);
 215        if (reg < 0)
 216                return reg;
 217
 218        /* Mask interrupts globally.  */
 219        reg |= MII_BCM54XX_ECR_IM;
 220        err = phy_write(phydev, MII_BCM54XX_ECR, reg);
 221        if (err < 0)
 222                return err;
 223
 224        /* Unmask events we are interested in.  */
 225        reg = ~(MII_BCM54XX_INT_DUPLEX |
 226                MII_BCM54XX_INT_SPEED |
 227                MII_BCM54XX_INT_LINK);
 228        err = phy_write(phydev, MII_BCM54XX_IMR, reg);
 229        if (err < 0)
 230                return err;
 231
 232        if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
 233             BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
 234            (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
 235                bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0);
 236
 237        if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
 238            (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
 239            (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
 240                bcm54xx_adjust_rxrefclk(phydev);
 241
 242        bcm54xx_phydsp_config(phydev);
 243
 244        return 0;
 245}
 246
 247static int bcm5482_config_init(struct phy_device *phydev)
 248{
 249        int err, reg;
 250
 251        err = bcm54xx_config_init(phydev);
 252
 253        if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
 254                /*
 255                 * Enable secondary SerDes and its use as an LED source
 256                 */
 257                reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD);
 258                bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD,
 259                                     reg |
 260                                     BCM5482_SHD_SSD_LEDM |
 261                                     BCM5482_SHD_SSD_EN);
 262
 263                /*
 264                 * Enable SGMII slave mode and auto-detection
 265                 */
 266                reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
 267                err = bcm54xx_exp_read(phydev, reg);
 268                if (err < 0)
 269                        return err;
 270                err = bcm54xx_exp_write(phydev, reg, err |
 271                                        BCM5482_SSD_SGMII_SLAVE_EN |
 272                                        BCM5482_SSD_SGMII_SLAVE_AD);
 273                if (err < 0)
 274                        return err;
 275
 276                /*
 277                 * Disable secondary SerDes powerdown
 278                 */
 279                reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
 280                err = bcm54xx_exp_read(phydev, reg);
 281                if (err < 0)
 282                        return err;
 283                err = bcm54xx_exp_write(phydev, reg,
 284                                        err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
 285                if (err < 0)
 286                        return err;
 287
 288                /*
 289                 * Select 1000BASE-X register set (primary SerDes)
 290                 */
 291                reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE);
 292                bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE,
 293                                     reg | BCM5482_SHD_MODE_1000BX);
 294
 295                /*
 296                 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
 297                 * (Use LED1 as secondary SerDes ACTIVITY LED)
 298                 */
 299                bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1,
 300                        BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
 301                        BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
 302
 303                /*
 304                 * Auto-negotiation doesn't seem to work quite right
 305                 * in this mode, so we disable it and force it to the
 306                 * right speed/duplex setting.  Only 'link status'
 307                 * is important.
 308                 */
 309                phydev->autoneg = AUTONEG_DISABLE;
 310                phydev->speed = SPEED_1000;
 311                phydev->duplex = DUPLEX_FULL;
 312        }
 313
 314        return err;
 315}
 316
 317static int bcm5482_read_status(struct phy_device *phydev)
 318{
 319        int err;
 320
 321        err = genphy_read_status(phydev);
 322
 323        if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
 324                /*
 325                 * Only link status matters for 1000Base-X mode, so force
 326                 * 1000 Mbit/s full-duplex status
 327                 */
 328                if (phydev->link) {
 329                        phydev->speed = SPEED_1000;
 330                        phydev->duplex = DUPLEX_FULL;
 331                }
 332        }
 333
 334        return err;
 335}
 336
 337static int bcm54xx_ack_interrupt(struct phy_device *phydev)
 338{
 339        int reg;
 340
 341        /* Clear pending interrupts.  */
 342        reg = phy_read(phydev, MII_BCM54XX_ISR);
 343        if (reg < 0)
 344                return reg;
 345
 346        return 0;
 347}
 348
 349static int bcm54xx_config_intr(struct phy_device *phydev)
 350{
 351        int reg, err;
 352
 353        reg = phy_read(phydev, MII_BCM54XX_ECR);
 354        if (reg < 0)
 355                return reg;
 356
 357        if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
 358                reg &= ~MII_BCM54XX_ECR_IM;
 359        else
 360                reg |= MII_BCM54XX_ECR_IM;
 361
 362        err = phy_write(phydev, MII_BCM54XX_ECR, reg);
 363        return err;
 364}
 365
 366static int bcm5481_config_aneg(struct phy_device *phydev)
 367{
 368        int ret;
 369
 370        /* Aneg firsly. */
 371        ret = genphy_config_aneg(phydev);
 372
 373        /* Then we can set up the delay. */
 374        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
 375                u16 reg;
 376
 377                /*
 378                 * There is no BCM5481 specification available, so down
 379                 * here is everything we know about "register 0x18". This
 380                 * at least helps BCM5481 to successfully receive packets
 381                 * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
 382                 * says: "This sets delay between the RXD and RXC signals
 383                 * instead of using trace lengths to achieve timing".
 384                 */
 385
 386                /* Set RDX clk delay. */
 387                reg = 0x7 | (0x7 << 12);
 388                phy_write(phydev, 0x18, reg);
 389
 390                reg = phy_read(phydev, 0x18);
 391                /* Set RDX-RXC skew. */
 392                reg |= (1 << 8);
 393                /* Write bits 14:0. */
 394                reg |= (1 << 15);
 395                phy_write(phydev, 0x18, reg);
 396        }
 397
 398        return ret;
 399}
 400
 401static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
 402{
 403        int val;
 404
 405        val = phy_read(phydev, reg);
 406        if (val < 0)
 407                return val;
 408
 409        return phy_write(phydev, reg, val | set);
 410}
 411
 412static int brcm_fet_config_init(struct phy_device *phydev)
 413{
 414        int reg, err, err2, brcmtest;
 415
 416        /* Reset the PHY to bring it to a known state. */
 417        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
 418        if (err < 0)
 419                return err;
 420
 421        reg = phy_read(phydev, MII_BRCM_FET_INTREG);
 422        if (reg < 0)
 423                return reg;
 424
 425        /* Unmask events we are interested in and mask interrupts globally. */
 426        reg = MII_BRCM_FET_IR_DUPLEX_EN |
 427              MII_BRCM_FET_IR_SPEED_EN |
 428              MII_BRCM_FET_IR_LINK_EN |
 429              MII_BRCM_FET_IR_ENABLE |
 430              MII_BRCM_FET_IR_MASK;
 431
 432        err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
 433        if (err < 0)
 434                return err;
 435
 436        /* Enable shadow register access */
 437        brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
 438        if (brcmtest < 0)
 439                return brcmtest;
 440
 441        reg = brcmtest | MII_BRCM_FET_BT_SRE;
 442
 443        err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
 444        if (err < 0)
 445                return err;
 446
 447        /* Set the LED mode */
 448        reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
 449        if (reg < 0) {
 450                err = reg;
 451                goto done;
 452        }
 453
 454        reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK;
 455        reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1;
 456
 457        err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
 458        if (err < 0)
 459                goto done;
 460
 461        /* Enable auto MDIX */
 462        err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
 463                                       MII_BRCM_FET_SHDW_MC_FAME);
 464        if (err < 0)
 465                goto done;
 466
 467        if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
 468                /* Enable auto power down */
 469                err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
 470                                               MII_BRCM_FET_SHDW_AS2_APDE);
 471        }
 472
 473done:
 474        /* Disable shadow register access */
 475        err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
 476        if (!err)
 477                err = err2;
 478
 479        return err;
 480}
 481
 482static int brcm_fet_ack_interrupt(struct phy_device *phydev)
 483{
 484        int reg;
 485
 486        /* Clear pending interrupts.  */
 487        reg = phy_read(phydev, MII_BRCM_FET_INTREG);
 488        if (reg < 0)
 489                return reg;
 490
 491        return 0;
 492}
 493
 494static int brcm_fet_config_intr(struct phy_device *phydev)
 495{
 496        int reg, err;
 497
 498        reg = phy_read(phydev, MII_BRCM_FET_INTREG);
 499        if (reg < 0)
 500                return reg;
 501
 502        if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
 503                reg &= ~MII_BRCM_FET_IR_MASK;
 504        else
 505                reg |= MII_BRCM_FET_IR_MASK;
 506
 507        err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
 508        return err;
 509}
 510
 511static struct phy_driver broadcom_drivers[] = {
 512{
 513        .phy_id         = PHY_ID_BCM5411,
 514        .phy_id_mask    = 0xfffffff0,
 515        .name           = "Broadcom BCM5411",
 516        .features       = PHY_GBIT_FEATURES |
 517                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 518        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 519        .config_init    = bcm54xx_config_init,
 520        .config_aneg    = genphy_config_aneg,
 521        .read_status    = genphy_read_status,
 522        .ack_interrupt  = bcm54xx_ack_interrupt,
 523        .config_intr    = bcm54xx_config_intr,
 524        .driver         = { .owner = THIS_MODULE },
 525}, {
 526        .phy_id         = PHY_ID_BCM5421,
 527        .phy_id_mask    = 0xfffffff0,
 528        .name           = "Broadcom BCM5421",
 529        .features       = PHY_GBIT_FEATURES |
 530                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 531        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 532        .config_init    = bcm54xx_config_init,
 533        .config_aneg    = genphy_config_aneg,
 534        .read_status    = genphy_read_status,
 535        .ack_interrupt  = bcm54xx_ack_interrupt,
 536        .config_intr    = bcm54xx_config_intr,
 537        .driver         = { .owner = THIS_MODULE },
 538}, {
 539        .phy_id         = PHY_ID_BCM5461,
 540        .phy_id_mask    = 0xfffffff0,
 541        .name           = "Broadcom BCM5461",
 542        .features       = PHY_GBIT_FEATURES |
 543                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 544        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 545        .config_init    = bcm54xx_config_init,
 546        .config_aneg    = genphy_config_aneg,
 547        .read_status    = genphy_read_status,
 548        .ack_interrupt  = bcm54xx_ack_interrupt,
 549        .config_intr    = bcm54xx_config_intr,
 550        .driver         = { .owner = THIS_MODULE },
 551}, {
 552        .phy_id         = PHY_ID_BCM54616S,
 553        .phy_id_mask    = 0xfffffff0,
 554        .name           = "Broadcom BCM54616S",
 555        .features       = PHY_GBIT_FEATURES |
 556                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 557        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 558        .config_init    = bcm54xx_config_init,
 559        .config_aneg    = genphy_config_aneg,
 560        .read_status    = genphy_read_status,
 561        .ack_interrupt  = bcm54xx_ack_interrupt,
 562        .config_intr    = bcm54xx_config_intr,
 563        .driver         = { .owner = THIS_MODULE },
 564}, {
 565        .phy_id         = PHY_ID_BCM5464,
 566        .phy_id_mask    = 0xfffffff0,
 567        .name           = "Broadcom BCM5464",
 568        .features       = PHY_GBIT_FEATURES |
 569                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 570        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 571        .config_init    = bcm54xx_config_init,
 572        .config_aneg    = genphy_config_aneg,
 573        .read_status    = genphy_read_status,
 574        .ack_interrupt  = bcm54xx_ack_interrupt,
 575        .config_intr    = bcm54xx_config_intr,
 576        .driver         = { .owner = THIS_MODULE },
 577}, {
 578        .phy_id         = PHY_ID_BCM5481,
 579        .phy_id_mask    = 0xfffffff0,
 580        .name           = "Broadcom BCM5481",
 581        .features       = PHY_GBIT_FEATURES |
 582                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 583        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 584        .config_init    = bcm54xx_config_init,
 585        .config_aneg    = bcm5481_config_aneg,
 586        .read_status    = genphy_read_status,
 587        .ack_interrupt  = bcm54xx_ack_interrupt,
 588        .config_intr    = bcm54xx_config_intr,
 589        .driver         = { .owner = THIS_MODULE },
 590}, {
 591        .phy_id         = PHY_ID_BCM5482,
 592        .phy_id_mask    = 0xfffffff0,
 593        .name           = "Broadcom BCM5482",
 594        .features       = PHY_GBIT_FEATURES |
 595                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 596        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 597        .config_init    = bcm5482_config_init,
 598        .config_aneg    = genphy_config_aneg,
 599        .read_status    = bcm5482_read_status,
 600        .ack_interrupt  = bcm54xx_ack_interrupt,
 601        .config_intr    = bcm54xx_config_intr,
 602        .driver         = { .owner = THIS_MODULE },
 603}, {
 604        .phy_id         = PHY_ID_BCM50610,
 605        .phy_id_mask    = 0xfffffff0,
 606        .name           = "Broadcom BCM50610",
 607        .features       = PHY_GBIT_FEATURES |
 608                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 609        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 610        .config_init    = bcm54xx_config_init,
 611        .config_aneg    = genphy_config_aneg,
 612        .read_status    = genphy_read_status,
 613        .ack_interrupt  = bcm54xx_ack_interrupt,
 614        .config_intr    = bcm54xx_config_intr,
 615        .driver         = { .owner = THIS_MODULE },
 616}, {
 617        .phy_id         = PHY_ID_BCM50610M,
 618        .phy_id_mask    = 0xfffffff0,
 619        .name           = "Broadcom BCM50610M",
 620        .features       = PHY_GBIT_FEATURES |
 621                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 622        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 623        .config_init    = bcm54xx_config_init,
 624        .config_aneg    = genphy_config_aneg,
 625        .read_status    = genphy_read_status,
 626        .ack_interrupt  = bcm54xx_ack_interrupt,
 627        .config_intr    = bcm54xx_config_intr,
 628        .driver         = { .owner = THIS_MODULE },
 629}, {
 630        .phy_id         = PHY_ID_BCM57780,
 631        .phy_id_mask    = 0xfffffff0,
 632        .name           = "Broadcom BCM57780",
 633        .features       = PHY_GBIT_FEATURES |
 634                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 635        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 636        .config_init    = bcm54xx_config_init,
 637        .config_aneg    = genphy_config_aneg,
 638        .read_status    = genphy_read_status,
 639        .ack_interrupt  = bcm54xx_ack_interrupt,
 640        .config_intr    = bcm54xx_config_intr,
 641        .driver         = { .owner = THIS_MODULE },
 642}, {
 643        .phy_id         = PHY_ID_BCMAC131,
 644        .phy_id_mask    = 0xfffffff0,
 645        .name           = "Broadcom BCMAC131",
 646        .features       = PHY_BASIC_FEATURES |
 647                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 648        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 649        .config_init    = brcm_fet_config_init,
 650        .config_aneg    = genphy_config_aneg,
 651        .read_status    = genphy_read_status,
 652        .ack_interrupt  = brcm_fet_ack_interrupt,
 653        .config_intr    = brcm_fet_config_intr,
 654        .driver         = { .owner = THIS_MODULE },
 655}, {
 656        .phy_id         = PHY_ID_BCM5241,
 657        .phy_id_mask    = 0xfffffff0,
 658        .name           = "Broadcom BCM5241",
 659        .features       = PHY_BASIC_FEATURES |
 660                          SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 661        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 662        .config_init    = brcm_fet_config_init,
 663        .config_aneg    = genphy_config_aneg,
 664        .read_status    = genphy_read_status,
 665        .ack_interrupt  = brcm_fet_ack_interrupt,
 666        .config_intr    = brcm_fet_config_intr,
 667        .driver         = { .owner = THIS_MODULE },
 668} };
 669
 670module_phy_driver(broadcom_drivers);
 671
 672static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
 673        { PHY_ID_BCM5411, 0xfffffff0 },
 674        { PHY_ID_BCM5421, 0xfffffff0 },
 675        { PHY_ID_BCM5461, 0xfffffff0 },
 676        { PHY_ID_BCM54616S, 0xfffffff0 },
 677        { PHY_ID_BCM5464, 0xfffffff0 },
 678        { PHY_ID_BCM5482, 0xfffffff0 },
 679        { PHY_ID_BCM5482, 0xfffffff0 },
 680        { PHY_ID_BCM50610, 0xfffffff0 },
 681        { PHY_ID_BCM50610M, 0xfffffff0 },
 682        { PHY_ID_BCM57780, 0xfffffff0 },
 683        { PHY_ID_BCMAC131, 0xfffffff0 },
 684        { PHY_ID_BCM5241, 0xfffffff0 },
 685        { }
 686};
 687
 688MODULE_DEVICE_TABLE(mdio, broadcom_tbl);
 689