Merge tag 'block-5.19-2022-07-08' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / drivers / net / phy / intel-xway.c
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
165 static const int xway_internal_delay[] = {0, 500, 1000, 1500, 2000, 2500,
166                                          3000, 3500};
167
168 static 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
232 static 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
286 static 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
301 static 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
309 static 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
332 static 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
350 static 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 };
457 module_phy_driver(xway_gphy);
458
459 static 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 };
472 MODULE_DEVICE_TABLE(mdio, xway_gphy_tbl);
473
474 MODULE_DESCRIPTION("Intel XWAY PHY driver");
475 MODULE_LICENSE("GPL");