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