linux/drivers/net/phy/intel-xway.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2012 Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
   4 * Copyright (C) 2016 Hauke Mehrtens <hauke@hauke-m.de>
   5 */
   6
   7#include <linux/mdio.h>
   8#include <linux/module.h>
   9#include <linux/phy.h>
  10#include <linux/of.h>
  11#include <linux/bitfield.h>
  12
  13#define XWAY_MDIO_MIICTRL               0x17    /* mii control */
  14#define XWAY_MDIO_IMASK                 0x19    /* interrupt mask */
  15#define XWAY_MDIO_ISTAT                 0x1A    /* interrupt status */
  16#define XWAY_MDIO_LED                   0x1B    /* led control */
  17
  18#define XWAY_MDIO_MIICTRL_RXSKEW_MASK   GENMASK(14, 12)
  19#define XWAY_MDIO_MIICTRL_TXSKEW_MASK   GENMASK(10, 8)
  20
  21/* bit 15:12 are reserved */
  22#define XWAY_MDIO_LED_LED3_EN           BIT(11) /* Enable the integrated function of LED3 */
  23#define XWAY_MDIO_LED_LED2_EN           BIT(10) /* Enable the integrated function of LED2 */
  24#define XWAY_MDIO_LED_LED1_EN           BIT(9)  /* Enable the integrated function of LED1 */
  25#define XWAY_MDIO_LED_LED0_EN           BIT(8)  /* Enable the integrated function of LED0 */
  26/* bit 7:4 are reserved */
  27#define XWAY_MDIO_LED_LED3_DA           BIT(3)  /* Direct Access to LED3 */
  28#define XWAY_MDIO_LED_LED2_DA           BIT(2)  /* Direct Access to LED2 */
  29#define XWAY_MDIO_LED_LED1_DA           BIT(1)  /* Direct Access to LED1 */
  30#define XWAY_MDIO_LED_LED0_DA           BIT(0)  /* Direct Access to LED0 */
  31
  32#define XWAY_MDIO_INIT_WOL              BIT(15) /* Wake-On-LAN */
  33#define XWAY_MDIO_INIT_MSRE             BIT(14)
  34#define XWAY_MDIO_INIT_NPRX             BIT(13)
  35#define XWAY_MDIO_INIT_NPTX             BIT(12)
  36#define XWAY_MDIO_INIT_ANE              BIT(11) /* Auto-Neg error */
  37#define XWAY_MDIO_INIT_ANC              BIT(10) /* Auto-Neg complete */
  38#define XWAY_MDIO_INIT_ADSC             BIT(5)  /* Link auto-downspeed detect */
  39#define XWAY_MDIO_INIT_MPIPC            BIT(4)
  40#define XWAY_MDIO_INIT_MDIXC            BIT(3)
  41#define XWAY_MDIO_INIT_DXMC             BIT(2)  /* Duplex mode change */
  42#define XWAY_MDIO_INIT_LSPC             BIT(1)  /* Link speed change */
  43#define XWAY_MDIO_INIT_LSTC             BIT(0)  /* Link state change */
  44#define XWAY_MDIO_INIT_MASK             (XWAY_MDIO_INIT_LSTC | \
  45                                         XWAY_MDIO_INIT_ADSC)
  46
  47#define ADVERTISED_MPD                  BIT(10) /* Multi-port device */
  48
  49/* LED Configuration */
  50#define XWAY_MMD_LEDCH                  0x01E0
  51/* Inverse of SCAN Function */
  52#define  XWAY_MMD_LEDCH_NACS_NONE       0x0000
  53#define  XWAY_MMD_LEDCH_NACS_LINK       0x0001
  54#define  XWAY_MMD_LEDCH_NACS_PDOWN      0x0002
  55#define  XWAY_MMD_LEDCH_NACS_EEE        0x0003
  56#define  XWAY_MMD_LEDCH_NACS_ANEG       0x0004
  57#define  XWAY_MMD_LEDCH_NACS_ABIST      0x0005
  58#define  XWAY_MMD_LEDCH_NACS_CDIAG      0x0006
  59#define  XWAY_MMD_LEDCH_NACS_TEST       0x0007
  60/* Slow Blink Frequency */
  61#define  XWAY_MMD_LEDCH_SBF_F02HZ       0x0000
  62#define  XWAY_MMD_LEDCH_SBF_F04HZ       0x0010
  63#define  XWAY_MMD_LEDCH_SBF_F08HZ       0x0020
  64#define  XWAY_MMD_LEDCH_SBF_F16HZ       0x0030
  65/* Fast Blink Frequency */
  66#define  XWAY_MMD_LEDCH_FBF_F02HZ       0x0000
  67#define  XWAY_MMD_LEDCH_FBF_F04HZ       0x0040
  68#define  XWAY_MMD_LEDCH_FBF_F08HZ       0x0080
  69#define  XWAY_MMD_LEDCH_FBF_F16HZ       0x00C0
  70/* LED Configuration */
  71#define XWAY_MMD_LEDCL                  0x01E1
  72/* Complex Blinking Configuration */
  73#define  XWAY_MMD_LEDCH_CBLINK_NONE     0x0000
  74#define  XWAY_MMD_LEDCH_CBLINK_LINK     0x0001
  75#define  XWAY_MMD_LEDCH_CBLINK_PDOWN    0x0002
  76#define  XWAY_MMD_LEDCH_CBLINK_EEE      0x0003
  77#define  XWAY_MMD_LEDCH_CBLINK_ANEG     0x0004
  78#define  XWAY_MMD_LEDCH_CBLINK_ABIST    0x0005
  79#define  XWAY_MMD_LEDCH_CBLINK_CDIAG    0x0006
  80#define  XWAY_MMD_LEDCH_CBLINK_TEST     0x0007
  81/* Complex SCAN Configuration */
  82#define  XWAY_MMD_LEDCH_SCAN_NONE       0x0000
  83#define  XWAY_MMD_LEDCH_SCAN_LINK       0x0010
  84#define  XWAY_MMD_LEDCH_SCAN_PDOWN      0x0020
  85#define  XWAY_MMD_LEDCH_SCAN_EEE        0x0030
  86#define  XWAY_MMD_LEDCH_SCAN_ANEG       0x0040
  87#define  XWAY_MMD_LEDCH_SCAN_ABIST      0x0050
  88#define  XWAY_MMD_LEDCH_SCAN_CDIAG      0x0060
  89#define  XWAY_MMD_LEDCH_SCAN_TEST       0x0070
  90/* Configuration for LED Pin x */
  91#define XWAY_MMD_LED0H                  0x01E2
  92/* Fast Blinking Configuration */
  93#define  XWAY_MMD_LEDxH_BLINKF_MASK     0x000F
  94#define  XWAY_MMD_LEDxH_BLINKF_NONE     0x0000
  95#define  XWAY_MMD_LEDxH_BLINKF_LINK10   0x0001
  96#define  XWAY_MMD_LEDxH_BLINKF_LINK100  0x0002
  97#define  XWAY_MMD_LEDxH_BLINKF_LINK10X  0x0003
  98#define  XWAY_MMD_LEDxH_BLINKF_LINK1000 0x0004
  99#define  XWAY_MMD_LEDxH_BLINKF_LINK10_0 0x0005
 100#define  XWAY_MMD_LEDxH_BLINKF_LINK100X 0x0006
 101#define  XWAY_MMD_LEDxH_BLINKF_LINK10XX 0x0007
 102#define  XWAY_MMD_LEDxH_BLINKF_PDOWN    0x0008
 103#define  XWAY_MMD_LEDxH_BLINKF_EEE      0x0009
 104#define  XWAY_MMD_LEDxH_BLINKF_ANEG     0x000A
 105#define  XWAY_MMD_LEDxH_BLINKF_ABIST    0x000B
 106#define  XWAY_MMD_LEDxH_BLINKF_CDIAG    0x000C
 107/* Constant On Configuration */
 108#define  XWAY_MMD_LEDxH_CON_MASK        0x00F0
 109#define  XWAY_MMD_LEDxH_CON_NONE        0x0000
 110#define  XWAY_MMD_LEDxH_CON_LINK10      0x0010
 111#define  XWAY_MMD_LEDxH_CON_LINK100     0x0020
 112#define  XWAY_MMD_LEDxH_CON_LINK10X     0x0030
 113#define  XWAY_MMD_LEDxH_CON_LINK1000    0x0040
 114#define  XWAY_MMD_LEDxH_CON_LINK10_0    0x0050
 115#define  XWAY_MMD_LEDxH_CON_LINK100X    0x0060
 116#define  XWAY_MMD_LEDxH_CON_LINK10XX    0x0070
 117#define  XWAY_MMD_LEDxH_CON_PDOWN       0x0080
 118#define  XWAY_MMD_LEDxH_CON_EEE         0x0090
 119#define  XWAY_MMD_LEDxH_CON_ANEG        0x00A0
 120#define  XWAY_MMD_LEDxH_CON_ABIST       0x00B0
 121#define  XWAY_MMD_LEDxH_CON_CDIAG       0x00C0
 122#define  XWAY_MMD_LEDxH_CON_COPPER      0x00D0
 123#define  XWAY_MMD_LEDxH_CON_FIBER       0x00E0
 124/* Configuration for LED Pin x */
 125#define XWAY_MMD_LED0L                  0x01E3
 126/* Pulsing Configuration */
 127#define  XWAY_MMD_LEDxL_PULSE_MASK      0x000F
 128#define  XWAY_MMD_LEDxL_PULSE_NONE      0x0000
 129#define  XWAY_MMD_LEDxL_PULSE_TXACT     0x0001
 130#define  XWAY_MMD_LEDxL_PULSE_RXACT     0x0002
 131#define  XWAY_MMD_LEDxL_PULSE_COL       0x0004
 132/* Slow Blinking Configuration */
 133#define  XWAY_MMD_LEDxL_BLINKS_MASK     0x00F0
 134#define  XWAY_MMD_LEDxL_BLINKS_NONE     0x0000
 135#define  XWAY_MMD_LEDxL_BLINKS_LINK10   0x0010
 136#define  XWAY_MMD_LEDxL_BLINKS_LINK100  0x0020
 137#define  XWAY_MMD_LEDxL_BLINKS_LINK10X  0x0030
 138#define  XWAY_MMD_LEDxL_BLINKS_LINK1000 0x0040
 139#define  XWAY_MMD_LEDxL_BLINKS_LINK10_0 0x0050
 140#define  XWAY_MMD_LEDxL_BLINKS_LINK100X 0x0060
 141#define  XWAY_MMD_LEDxL_BLINKS_LINK10XX 0x0070
 142#define  XWAY_MMD_LEDxL_BLINKS_PDOWN    0x0080
 143#define  XWAY_MMD_LEDxL_BLINKS_EEE      0x0090
 144#define  XWAY_MMD_LEDxL_BLINKS_ANEG     0x00A0
 145#define  XWAY_MMD_LEDxL_BLINKS_ABIST    0x00B0
 146#define  XWAY_MMD_LEDxL_BLINKS_CDIAG    0x00C0
 147#define XWAY_MMD_LED1H                  0x01E4
 148#define XWAY_MMD_LED1L                  0x01E5
 149#define XWAY_MMD_LED2H                  0x01E6
 150#define XWAY_MMD_LED2L                  0x01E7
 151#define XWAY_MMD_LED3H                  0x01E8
 152#define XWAY_MMD_LED3L                  0x01E9
 153
 154#define PHY_ID_PHY11G_1_3               0x030260D1
 155#define PHY_ID_PHY22F_1_3               0x030260E1
 156#define PHY_ID_PHY11G_1_4               0xD565A400
 157#define PHY_ID_PHY22F_1_4               0xD565A410
 158#define PHY_ID_PHY11G_1_5               0xD565A401
 159#define PHY_ID_PHY22F_1_5               0xD565A411
 160#define PHY_ID_PHY11G_VR9_1_1           0xD565A408
 161#define PHY_ID_PHY22F_VR9_1_1           0xD565A418
 162#define PHY_ID_PHY11G_VR9_1_2           0xD565A409
 163#define PHY_ID_PHY22F_VR9_1_2           0xD565A419
 164
 165static const int xway_internal_delay[] = {0, 500, 1000, 1500, 2000, 2500,
 166                                         3000, 3500};
 167
 168static int xway_gphy_rgmii_init(struct phy_device *phydev)
 169{
 170        struct device *dev = &phydev->mdio.dev;
 171        unsigned int delay_size = ARRAY_SIZE(xway_internal_delay);
 172        s32 int_delay;
 173        int val = 0;
 174
 175        if (!phy_interface_is_rgmii(phydev))
 176                return 0;
 177
 178        /* Existing behavior was to use default pin strapping delay in rgmii
 179         * mode, but rgmii should have meant no delay.  Warn existing users,
 180         * but do not change anything at the moment.
 181         */
 182        if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
 183                u16 txskew, rxskew;
 184
 185                val = phy_read(phydev, XWAY_MDIO_MIICTRL);
 186                if (val < 0)
 187                        return val;
 188
 189                txskew = FIELD_GET(XWAY_MDIO_MIICTRL_TXSKEW_MASK, val);
 190                rxskew = FIELD_GET(XWAY_MDIO_MIICTRL_RXSKEW_MASK, val);
 191
 192                if (txskew > 0 || rxskew > 0)
 193                        phydev_warn(phydev,
 194                                    "PHY has delays (e.g. via pin strapping), but phy-mode = 'rgmii'\n"
 195                                    "Should be 'rgmii-id' to use internal delays txskew:%d ps rxskew:%d ps\n",
 196                                    xway_internal_delay[txskew],
 197                                    xway_internal_delay[rxskew]);
 198                return 0;
 199        }
 200
 201        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
 202            phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
 203                int_delay = phy_get_internal_delay(phydev, dev,
 204                                                   xway_internal_delay,
 205                                                   delay_size, true);
 206
 207                /* if rx-internal-delay-ps is missing, use default of 2.0 ns */
 208                if (int_delay < 0)
 209                        int_delay = 4; /* 2000 ps */
 210
 211                val |= FIELD_PREP(XWAY_MDIO_MIICTRL_RXSKEW_MASK, int_delay);
 212        }
 213
 214        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
 215            phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
 216                int_delay = phy_get_internal_delay(phydev, dev,
 217                                                   xway_internal_delay,
 218                                                   delay_size, false);
 219
 220                /* if tx-internal-delay-ps is missing, use default of 2.0 ns */
 221                if (int_delay < 0)
 222                        int_delay = 4; /* 2000 ps */
 223
 224                val |= FIELD_PREP(XWAY_MDIO_MIICTRL_TXSKEW_MASK, int_delay);
 225        }
 226
 227        return phy_modify(phydev, XWAY_MDIO_MIICTRL,
 228                          XWAY_MDIO_MIICTRL_RXSKEW_MASK |
 229                          XWAY_MDIO_MIICTRL_TXSKEW_MASK, val);
 230}
 231
 232static int xway_gphy_config_init(struct phy_device *phydev)
 233{
 234        int err;
 235        u32 ledxh;
 236        u32 ledxl;
 237
 238        /* Mask all interrupts */
 239        err = phy_write(phydev, XWAY_MDIO_IMASK, 0);
 240        if (err)
 241                return err;
 242
 243        /* Clear all pending interrupts */
 244        phy_read(phydev, XWAY_MDIO_ISTAT);
 245
 246        /* Ensure that integrated led function is enabled for all leds */
 247        err = phy_write(phydev, XWAY_MDIO_LED,
 248                        XWAY_MDIO_LED_LED0_EN |
 249                        XWAY_MDIO_LED_LED1_EN |
 250                        XWAY_MDIO_LED_LED2_EN |
 251                        XWAY_MDIO_LED_LED3_EN);
 252        if (err)
 253                return err;
 254
 255        phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDCH,
 256                      XWAY_MMD_LEDCH_NACS_NONE |
 257                      XWAY_MMD_LEDCH_SBF_F02HZ |
 258                      XWAY_MMD_LEDCH_FBF_F16HZ);
 259        phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDCL,
 260                      XWAY_MMD_LEDCH_CBLINK_NONE |
 261                      XWAY_MMD_LEDCH_SCAN_NONE);
 262
 263        /**
 264         * In most cases only one LED is connected to this phy, so
 265         * configure them all to constant on and pulse mode. LED3 is
 266         * only available in some packages, leave it in its reset
 267         * configuration.
 268         */
 269        ledxh = XWAY_MMD_LEDxH_BLINKF_NONE | XWAY_MMD_LEDxH_CON_LINK10XX;
 270        ledxl = XWAY_MMD_LEDxL_PULSE_TXACT | XWAY_MMD_LEDxL_PULSE_RXACT |
 271                XWAY_MMD_LEDxL_BLINKS_NONE;
 272        phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED0H, ledxh);
 273        phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED0L, ledxl);
 274        phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED1H, ledxh);
 275        phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED1L, ledxl);
 276        phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2H, ledxh);
 277        phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2L, ledxl);
 278
 279        err = xway_gphy_rgmii_init(phydev);
 280        if (err)
 281                return err;
 282
 283        return 0;
 284}
 285
 286static int xway_gphy14_config_aneg(struct phy_device *phydev)
 287{
 288        int reg, err;
 289
 290        /* Advertise as multi-port device, see IEEE802.3-2002 40.5.1.1 */
 291        /* This is a workaround for an errata in rev < 1.5 devices */
 292        reg = phy_read(phydev, MII_CTRL1000);
 293        reg |= ADVERTISED_MPD;
 294        err = phy_write(phydev, MII_CTRL1000, reg);
 295        if (err)
 296                return err;
 297
 298        return genphy_config_aneg(phydev);
 299}
 300
 301static int xway_gphy_ack_interrupt(struct phy_device *phydev)
 302{
 303        int reg;
 304
 305        reg = phy_read(phydev, XWAY_MDIO_ISTAT);
 306        return (reg < 0) ? reg : 0;
 307}
 308
 309static int xway_gphy_config_intr(struct phy_device *phydev)
 310{
 311        u16 mask = 0;
 312        int err;
 313
 314        if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
 315                err = xway_gphy_ack_interrupt(phydev);
 316                if (err)
 317                        return err;
 318
 319                mask = XWAY_MDIO_INIT_MASK;
 320                err = phy_write(phydev, XWAY_MDIO_IMASK, mask);
 321        } else {
 322                err = phy_write(phydev, XWAY_MDIO_IMASK, mask);
 323                if (err)
 324                        return err;
 325
 326                err = xway_gphy_ack_interrupt(phydev);
 327        }
 328
 329        return err;
 330}
 331
 332static irqreturn_t xway_gphy_handle_interrupt(struct phy_device *phydev)
 333{
 334        int irq_status;
 335
 336        irq_status = phy_read(phydev, XWAY_MDIO_ISTAT);
 337        if (irq_status < 0) {
 338                phy_error(phydev);
 339                return IRQ_NONE;
 340        }
 341
 342        if (!(irq_status & XWAY_MDIO_INIT_MASK))
 343                return IRQ_NONE;
 344
 345        phy_trigger_machine(phydev);
 346
 347        return IRQ_HANDLED;
 348}
 349
 350static struct phy_driver xway_gphy[] = {
 351        {
 352                .phy_id         = PHY_ID_PHY11G_1_3,
 353                .phy_id_mask    = 0xffffffff,
 354                .name           = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.3",
 355                /* PHY_GBIT_FEATURES */
 356                .config_init    = xway_gphy_config_init,
 357                .config_aneg    = xway_gphy14_config_aneg,
 358                .handle_interrupt = xway_gphy_handle_interrupt,
 359                .config_intr    = xway_gphy_config_intr,
 360                .suspend        = genphy_suspend,
 361                .resume         = genphy_resume,
 362        }, {
 363                .phy_id         = PHY_ID_PHY22F_1_3,
 364                .phy_id_mask    = 0xffffffff,
 365                .name           = "Intel XWAY PHY22F (PEF 7061) v1.3",
 366                /* PHY_BASIC_FEATURES */
 367                .config_init    = xway_gphy_config_init,
 368                .config_aneg    = xway_gphy14_config_aneg,
 369                .handle_interrupt = xway_gphy_handle_interrupt,
 370                .config_intr    = xway_gphy_config_intr,
 371                .suspend        = genphy_suspend,
 372                .resume         = genphy_resume,
 373        }, {
 374                .phy_id         = PHY_ID_PHY11G_1_4,
 375                .phy_id_mask    = 0xffffffff,
 376                .name           = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.4",
 377                /* PHY_GBIT_FEATURES */
 378                .config_init    = xway_gphy_config_init,
 379                .config_aneg    = xway_gphy14_config_aneg,
 380                .handle_interrupt = xway_gphy_handle_interrupt,
 381                .config_intr    = xway_gphy_config_intr,
 382                .suspend        = genphy_suspend,
 383                .resume         = genphy_resume,
 384        }, {
 385                .phy_id         = PHY_ID_PHY22F_1_4,
 386                .phy_id_mask    = 0xffffffff,
 387                .name           = "Intel XWAY PHY22F (PEF 7061) v1.4",
 388                /* PHY_BASIC_FEATURES */
 389                .config_init    = xway_gphy_config_init,
 390                .config_aneg    = xway_gphy14_config_aneg,
 391                .handle_interrupt = xway_gphy_handle_interrupt,
 392                .config_intr    = xway_gphy_config_intr,
 393                .suspend        = genphy_suspend,
 394                .resume         = genphy_resume,
 395        }, {
 396                .phy_id         = PHY_ID_PHY11G_1_5,
 397                .phy_id_mask    = 0xffffffff,
 398                .name           = "Intel XWAY PHY11G (PEF 7071/PEF 7072) v1.5 / v1.6",
 399                /* PHY_GBIT_FEATURES */
 400                .config_init    = xway_gphy_config_init,
 401                .handle_interrupt = xway_gphy_handle_interrupt,
 402                .config_intr    = xway_gphy_config_intr,
 403                .suspend        = genphy_suspend,
 404                .resume         = genphy_resume,
 405        }, {
 406                .phy_id         = PHY_ID_PHY22F_1_5,
 407                .phy_id_mask    = 0xffffffff,
 408                .name           = "Intel XWAY PHY22F (PEF 7061) v1.5 / v1.6",
 409                /* PHY_BASIC_FEATURES */
 410                .config_init    = xway_gphy_config_init,
 411                .handle_interrupt = xway_gphy_handle_interrupt,
 412                .config_intr    = xway_gphy_config_intr,
 413                .suspend        = genphy_suspend,
 414                .resume         = genphy_resume,
 415        }, {
 416                .phy_id         = PHY_ID_PHY11G_VR9_1_1,
 417                .phy_id_mask    = 0xffffffff,
 418                .name           = "Intel XWAY PHY11G (xRX v1.1 integrated)",
 419                /* PHY_GBIT_FEATURES */
 420                .config_init    = xway_gphy_config_init,
 421                .handle_interrupt = xway_gphy_handle_interrupt,
 422                .config_intr    = xway_gphy_config_intr,
 423                .suspend        = genphy_suspend,
 424                .resume         = genphy_resume,
 425        }, {
 426                .phy_id         = PHY_ID_PHY22F_VR9_1_1,
 427                .phy_id_mask    = 0xffffffff,
 428                .name           = "Intel XWAY PHY22F (xRX v1.1 integrated)",
 429                /* PHY_BASIC_FEATURES */
 430                .config_init    = xway_gphy_config_init,
 431                .handle_interrupt = xway_gphy_handle_interrupt,
 432                .config_intr    = xway_gphy_config_intr,
 433                .suspend        = genphy_suspend,
 434                .resume         = genphy_resume,
 435        }, {
 436                .phy_id         = PHY_ID_PHY11G_VR9_1_2,
 437                .phy_id_mask    = 0xffffffff,
 438                .name           = "Intel XWAY PHY11G (xRX v1.2 integrated)",
 439                /* PHY_GBIT_FEATURES */
 440                .config_init    = xway_gphy_config_init,
 441                .handle_interrupt = xway_gphy_handle_interrupt,
 442                .config_intr    = xway_gphy_config_intr,
 443                .suspend        = genphy_suspend,
 444                .resume         = genphy_resume,
 445        }, {
 446                .phy_id         = PHY_ID_PHY22F_VR9_1_2,
 447                .phy_id_mask    = 0xffffffff,
 448                .name           = "Intel XWAY PHY22F (xRX v1.2 integrated)",
 449                /* PHY_BASIC_FEATURES */
 450                .config_init    = xway_gphy_config_init,
 451                .handle_interrupt = xway_gphy_handle_interrupt,
 452                .config_intr    = xway_gphy_config_intr,
 453                .suspend        = genphy_suspend,
 454                .resume         = genphy_resume,
 455        },
 456};
 457module_phy_driver(xway_gphy);
 458
 459static struct mdio_device_id __maybe_unused xway_gphy_tbl[] = {
 460        { PHY_ID_PHY11G_1_3, 0xffffffff },
 461        { PHY_ID_PHY22F_1_3, 0xffffffff },
 462        { PHY_ID_PHY11G_1_4, 0xffffffff },
 463        { PHY_ID_PHY22F_1_4, 0xffffffff },
 464        { PHY_ID_PHY11G_1_5, 0xffffffff },
 465        { PHY_ID_PHY22F_1_5, 0xffffffff },
 466        { PHY_ID_PHY11G_VR9_1_1, 0xffffffff },
 467        { PHY_ID_PHY22F_VR9_1_1, 0xffffffff },
 468        { PHY_ID_PHY11G_VR9_1_2, 0xffffffff },
 469        { PHY_ID_PHY22F_VR9_1_2, 0xffffffff },
 470        { }
 471};
 472MODULE_DEVICE_TABLE(mdio, xway_gphy_tbl);
 473
 474MODULE_DESCRIPTION("Intel XWAY PHY driver");
 475MODULE_LICENSE("GPL");
 476