e2afdce0a43781a7dc6876e20eecbb9df8f38f93
[pandora-kernel.git] / drivers / net / phy / marvell.c
1 /*
2  * drivers/net/phy/marvell.c
3  *
4  * Driver for Marvell PHYs
5  *
6  * Author: Andy Fleming
7  *
8  * Copyright (c) 2004 Freescale Semiconductor, Inc.
9  *
10  * This program is free software; you can redistribute  it and/or modify it
11  * under  the terms of  the GNU General  Public License as published by the
12  * Free Software Foundation;  either version 2 of the  License, or (at your
13  * option) any later version.
14  *
15  */
16 #include <linux/kernel.h>
17 #include <linux/string.h>
18 #include <linux/errno.h>
19 #include <linux/unistd.h>
20 #include <linux/interrupt.h>
21 #include <linux/init.h>
22 #include <linux/delay.h>
23 #include <linux/netdevice.h>
24 #include <linux/etherdevice.h>
25 #include <linux/skbuff.h>
26 #include <linux/spinlock.h>
27 #include <linux/mm.h>
28 #include <linux/module.h>
29 #include <linux/mii.h>
30 #include <linux/ethtool.h>
31 #include <linux/phy.h>
32 #include <linux/marvell_phy.h>
33
34 #include <asm/io.h>
35 #include <asm/irq.h>
36 #include <asm/uaccess.h>
37
38 #define MII_M1011_IEVENT                0x13
39 #define MII_M1011_IEVENT_CLEAR          0x0000
40
41 #define MII_M1011_IMASK                 0x12
42 #define MII_M1011_IMASK_INIT            0x6400
43 #define MII_M1011_IMASK_CLEAR           0x0000
44
45 #define MII_M1011_PHY_SCR               0x10
46 #define MII_M1011_PHY_SCR_AUTO_CROSS    0x0060
47
48 #define MII_M1145_PHY_EXT_CR            0x14
49 #define MII_M1145_RGMII_RX_DELAY        0x0080
50 #define MII_M1145_RGMII_TX_DELAY        0x0002
51
52 #define MII_M1111_PHY_LED_CONTROL       0x18
53 #define MII_M1111_PHY_LED_DIRECT        0x4100
54 #define MII_M1111_PHY_LED_COMBINE       0x411c
55 #define MII_M1111_PHY_EXT_CR            0x14
56 #define MII_M1111_RX_DELAY              0x80
57 #define MII_M1111_TX_DELAY              0x2
58 #define MII_M1111_PHY_EXT_SR            0x1b
59
60 #define MII_M1111_HWCFG_MODE_MASK               0xf
61 #define MII_M1111_HWCFG_MODE_COPPER_RGMII       0xb
62 #define MII_M1111_HWCFG_MODE_FIBER_RGMII        0x3
63 #define MII_M1111_HWCFG_MODE_SGMII_NO_CLK       0x4
64 #define MII_M1111_HWCFG_MODE_COPPER_RTBI        0x9
65 #define MII_M1111_HWCFG_FIBER_COPPER_AUTO       0x8000
66 #define MII_M1111_HWCFG_FIBER_COPPER_RES        0x2000
67
68 #define MII_M1111_COPPER                0
69 #define MII_M1111_FIBER                 1
70
71 #define MII_88E1121_PHY_MSCR_PAGE       2
72 #define MII_88E1121_PHY_MSCR_REG        21
73 #define MII_88E1121_PHY_MSCR_RX_DELAY   BIT(5)
74 #define MII_88E1121_PHY_MSCR_TX_DELAY   BIT(4)
75 #define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4))
76
77 #define MII_88EC048_PHY_MSCR1_REG       16
78 #define MII_88EC048_PHY_MSCR1_PAD_ODD   BIT(6)
79
80 #define MII_88E1121_PHY_LED_CTRL        16
81 #define MII_88E1121_PHY_LED_PAGE        3
82 #define MII_88E1121_PHY_LED_DEF         0x0030
83 #define MII_88E1121_PHY_PAGE            22
84
85 #define MII_M1011_PHY_STATUS            0x11
86 #define MII_M1011_PHY_STATUS_1000       0x8000
87 #define MII_M1011_PHY_STATUS_100        0x4000
88 #define MII_M1011_PHY_STATUS_SPD_MASK   0xc000
89 #define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000
90 #define MII_M1011_PHY_STATUS_RESOLVED   0x0800
91 #define MII_M1011_PHY_STATUS_LINK       0x0400
92
93
94 MODULE_DESCRIPTION("Marvell PHY driver");
95 MODULE_AUTHOR("Andy Fleming");
96 MODULE_LICENSE("GPL");
97
98 static int marvell_ack_interrupt(struct phy_device *phydev)
99 {
100         int err;
101
102         /* Clear the interrupts by reading the reg */
103         err = phy_read(phydev, MII_M1011_IEVENT);
104
105         if (err < 0)
106                 return err;
107
108         return 0;
109 }
110
111 static int marvell_config_intr(struct phy_device *phydev)
112 {
113         int err;
114
115         if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
116                 err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
117         else
118                 err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
119
120         return err;
121 }
122
123 static int marvell_config_aneg(struct phy_device *phydev)
124 {
125         int err;
126
127         /* The Marvell PHY has an errata which requires
128          * that certain registers get written in order
129          * to restart autonegotiation */
130         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
131
132         if (err < 0)
133                 return err;
134
135         err = phy_write(phydev, 0x1d, 0x1f);
136         if (err < 0)
137                 return err;
138
139         err = phy_write(phydev, 0x1e, 0x200c);
140         if (err < 0)
141                 return err;
142
143         err = phy_write(phydev, 0x1d, 0x5);
144         if (err < 0)
145                 return err;
146
147         err = phy_write(phydev, 0x1e, 0);
148         if (err < 0)
149                 return err;
150
151         err = phy_write(phydev, 0x1e, 0x100);
152         if (err < 0)
153                 return err;
154
155         err = phy_write(phydev, MII_M1011_PHY_SCR,
156                         MII_M1011_PHY_SCR_AUTO_CROSS);
157         if (err < 0)
158                 return err;
159
160         err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
161                         MII_M1111_PHY_LED_DIRECT);
162         if (err < 0)
163                 return err;
164
165         err = genphy_config_aneg(phydev);
166         if (err < 0)
167                 return err;
168
169         if (phydev->autoneg != AUTONEG_ENABLE) {
170                 int bmcr;
171
172                 /*
173                  * A write to speed/duplex bits (that is performed by
174                  * genphy_config_aneg() call above) must be followed by
175                  * a software reset. Otherwise, the write has no effect.
176                  */
177                 bmcr = phy_read(phydev, MII_BMCR);
178                 if (bmcr < 0)
179                         return bmcr;
180
181                 err = phy_write(phydev, MII_BMCR, bmcr | BMCR_RESET);
182                 if (err < 0)
183                         return err;
184         }
185
186         return 0;
187 }
188
189 static int m88e1121_config_aneg(struct phy_device *phydev)
190 {
191         int err, oldpage, mscr;
192
193         oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE);
194
195         err = phy_write(phydev, MII_88E1121_PHY_PAGE,
196                         MII_88E1121_PHY_MSCR_PAGE);
197         if (err < 0)
198                 return err;
199
200         if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
201             (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
202             (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
203             (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
204
205                 mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) &
206                         MII_88E1121_PHY_MSCR_DELAY_MASK;
207
208                 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
209                         mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
210                                  MII_88E1121_PHY_MSCR_TX_DELAY);
211                 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
212                         mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
213                 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
214                         mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
215
216                 err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
217                 if (err < 0)
218                         return err;
219         }
220
221         phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
222
223         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
224         if (err < 0)
225                 return err;
226
227         err = phy_write(phydev, MII_M1011_PHY_SCR,
228                         MII_M1011_PHY_SCR_AUTO_CROSS);
229         if (err < 0)
230                 return err;
231
232         oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE);
233
234         phy_write(phydev, MII_88E1121_PHY_PAGE, MII_88E1121_PHY_LED_PAGE);
235         phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF);
236         phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
237
238         err = genphy_config_aneg(phydev);
239
240         return err;
241 }
242
243 static int m88ec048_config_aneg(struct phy_device *phydev)
244 {
245         int err, oldpage, mscr;
246
247         oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE);
248
249         err = phy_write(phydev, MII_88E1121_PHY_PAGE,
250                         MII_88E1121_PHY_MSCR_PAGE);
251         if (err < 0)
252                 return err;
253
254         mscr = phy_read(phydev, MII_88EC048_PHY_MSCR1_REG);
255         mscr |= MII_88EC048_PHY_MSCR1_PAD_ODD;
256
257         err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
258         if (err < 0)
259                 return err;
260
261         err = phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
262         if (err < 0)
263                 return err;
264
265         return m88e1121_config_aneg(phydev);
266 }
267
268 static int m88e1111_config_init(struct phy_device *phydev)
269 {
270         int err;
271         int temp;
272
273         /* Enable Fiber/Copper auto selection */
274         temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
275         temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO;
276         phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
277
278         temp = phy_read(phydev, MII_BMCR);
279         temp |= BMCR_RESET;
280         phy_write(phydev, MII_BMCR, temp);
281
282         if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
283             (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
284             (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
285             (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
286
287                 temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
288                 if (temp < 0)
289                         return temp;
290
291                 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
292                         temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
293                 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
294                         temp &= ~MII_M1111_TX_DELAY;
295                         temp |= MII_M1111_RX_DELAY;
296                 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
297                         temp &= ~MII_M1111_RX_DELAY;
298                         temp |= MII_M1111_TX_DELAY;
299                 }
300
301                 err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
302                 if (err < 0)
303                         return err;
304
305                 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
306                 if (temp < 0)
307                         return temp;
308
309                 temp &= ~(MII_M1111_HWCFG_MODE_MASK);
310
311                 if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES)
312                         temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII;
313                 else
314                         temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII;
315
316                 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
317                 if (err < 0)
318                         return err;
319         }
320
321         if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
322                 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
323                 if (temp < 0)
324                         return temp;
325
326                 temp &= ~(MII_M1111_HWCFG_MODE_MASK);
327                 temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK;
328                 temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
329
330                 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
331                 if (err < 0)
332                         return err;
333         }
334
335         if (phydev->interface == PHY_INTERFACE_MODE_RTBI) {
336                 temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
337                 if (temp < 0)
338                         return temp;
339                 temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
340                 err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
341                 if (err < 0)
342                         return err;
343
344                 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
345                 if (temp < 0)
346                         return temp;
347                 temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES);
348                 temp |= 0x7 | MII_M1111_HWCFG_FIBER_COPPER_AUTO;
349                 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
350                 if (err < 0)
351                         return err;
352
353                 /* soft reset */
354                 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
355                 if (err < 0)
356                         return err;
357                 do
358                         temp = phy_read(phydev, MII_BMCR);
359                 while (temp & BMCR_RESET);
360
361                 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
362                 if (temp < 0)
363                         return temp;
364                 temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES);
365                 temp |= MII_M1111_HWCFG_MODE_COPPER_RTBI | MII_M1111_HWCFG_FIBER_COPPER_AUTO;
366                 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
367                 if (err < 0)
368                         return err;
369         }
370
371
372         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
373         if (err < 0)
374                 return err;
375
376         return 0;
377 }
378
379 static int m88e1118_config_aneg(struct phy_device *phydev)
380 {
381         int err;
382
383         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
384         if (err < 0)
385                 return err;
386
387         err = phy_write(phydev, MII_M1011_PHY_SCR,
388                         MII_M1011_PHY_SCR_AUTO_CROSS);
389         if (err < 0)
390                 return err;
391
392         err = genphy_config_aneg(phydev);
393         return 0;
394 }
395
396 static int m88e1118_config_init(struct phy_device *phydev)
397 {
398         int err;
399
400         /* Change address */
401         err = phy_write(phydev, 0x16, 0x0002);
402         if (err < 0)
403                 return err;
404
405         /* Enable 1000 Mbit */
406         err = phy_write(phydev, 0x15, 0x1070);
407         if (err < 0)
408                 return err;
409
410         /* Change address */
411         err = phy_write(phydev, 0x16, 0x0003);
412         if (err < 0)
413                 return err;
414
415         /* Adjust LED Control */
416         if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS)
417                 err = phy_write(phydev, 0x10, 0x1100);
418         else
419                 err = phy_write(phydev, 0x10, 0x021e);
420         if (err < 0)
421                 return err;
422
423         /* Reset address */
424         err = phy_write(phydev, 0x16, 0x0);
425         if (err < 0)
426                 return err;
427
428         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
429         if (err < 0)
430                 return err;
431
432         return 0;
433 }
434
435 static int m88e1145_config_init(struct phy_device *phydev)
436 {
437         int err;
438
439         /* Take care of errata E0 & E1 */
440         err = phy_write(phydev, 0x1d, 0x001b);
441         if (err < 0)
442                 return err;
443
444         err = phy_write(phydev, 0x1e, 0x418f);
445         if (err < 0)
446                 return err;
447
448         err = phy_write(phydev, 0x1d, 0x0016);
449         if (err < 0)
450                 return err;
451
452         err = phy_write(phydev, 0x1e, 0xa2da);
453         if (err < 0)
454                 return err;
455
456         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
457                 int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR);
458                 if (temp < 0)
459                         return temp;
460
461                 temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY);
462
463                 err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp);
464                 if (err < 0)
465                         return err;
466
467                 if (phydev->dev_flags & MARVELL_PHY_M1145_FLAGS_RESISTANCE) {
468                         err = phy_write(phydev, 0x1d, 0x0012);
469                         if (err < 0)
470                                 return err;
471
472                         temp = phy_read(phydev, 0x1e);
473                         if (temp < 0)
474                                 return temp;
475
476                         temp &= 0xf03f;
477                         temp |= 2 << 9; /* 36 ohm */
478                         temp |= 2 << 6; /* 39 ohm */
479
480                         err = phy_write(phydev, 0x1e, temp);
481                         if (err < 0)
482                                 return err;
483
484                         err = phy_write(phydev, 0x1d, 0x3);
485                         if (err < 0)
486                                 return err;
487
488                         err = phy_write(phydev, 0x1e, 0x8000);
489                         if (err < 0)
490                                 return err;
491                 }
492         }
493
494         return 0;
495 }
496
497 /* marvell_read_status
498  *
499  * Generic status code does not detect Fiber correctly!
500  * Description:
501  *   Check the link, then figure out the current state
502  *   by comparing what we advertise with what the link partner
503  *   advertises.  Start by checking the gigabit possibilities,
504  *   then move on to 10/100.
505  */
506 static int marvell_read_status(struct phy_device *phydev)
507 {
508         int adv;
509         int err;
510         int lpa;
511         int status = 0;
512
513         /* Update the link, but return if there
514          * was an error */
515         err = genphy_update_link(phydev);
516         if (err)
517                 return err;
518
519         if (AUTONEG_ENABLE == phydev->autoneg) {
520                 status = phy_read(phydev, MII_M1011_PHY_STATUS);
521                 if (status < 0)
522                         return status;
523
524                 lpa = phy_read(phydev, MII_LPA);
525                 if (lpa < 0)
526                         return lpa;
527
528                 adv = phy_read(phydev, MII_ADVERTISE);
529                 if (adv < 0)
530                         return adv;
531
532                 lpa &= adv;
533
534                 if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
535                         phydev->duplex = DUPLEX_FULL;
536                 else
537                         phydev->duplex = DUPLEX_HALF;
538
539                 status = status & MII_M1011_PHY_STATUS_SPD_MASK;
540                 phydev->pause = phydev->asym_pause = 0;
541
542                 switch (status) {
543                 case MII_M1011_PHY_STATUS_1000:
544                         phydev->speed = SPEED_1000;
545                         break;
546
547                 case MII_M1011_PHY_STATUS_100:
548                         phydev->speed = SPEED_100;
549                         break;
550
551                 default:
552                         phydev->speed = SPEED_10;
553                         break;
554                 }
555
556                 if (phydev->duplex == DUPLEX_FULL) {
557                         phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
558                         phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
559                 }
560         } else {
561                 int bmcr = phy_read(phydev, MII_BMCR);
562
563                 if (bmcr < 0)
564                         return bmcr;
565
566                 if (bmcr & BMCR_FULLDPLX)
567                         phydev->duplex = DUPLEX_FULL;
568                 else
569                         phydev->duplex = DUPLEX_HALF;
570
571                 if (bmcr & BMCR_SPEED1000)
572                         phydev->speed = SPEED_1000;
573                 else if (bmcr & BMCR_SPEED100)
574                         phydev->speed = SPEED_100;
575                 else
576                         phydev->speed = SPEED_10;
577
578                 phydev->pause = phydev->asym_pause = 0;
579         }
580
581         return 0;
582 }
583
584 static int m88e1121_did_interrupt(struct phy_device *phydev)
585 {
586         int imask;
587
588         imask = phy_read(phydev, MII_M1011_IEVENT);
589
590         if (imask & MII_M1011_IMASK_INIT)
591                 return 1;
592
593         return 0;
594 }
595
596 static struct phy_driver marvell_drivers[] = {
597         {
598                 .phy_id = MARVELL_PHY_ID_88E1101,
599                 .phy_id_mask = MARVELL_PHY_ID_MASK,
600                 .name = "Marvell 88E1101",
601                 .features = PHY_GBIT_FEATURES,
602                 .flags = PHY_HAS_INTERRUPT,
603                 .config_aneg = &marvell_config_aneg,
604                 .read_status = &genphy_read_status,
605                 .ack_interrupt = &marvell_ack_interrupt,
606                 .config_intr = &marvell_config_intr,
607                 .driver = { .owner = THIS_MODULE },
608         },
609         {
610                 .phy_id = MARVELL_PHY_ID_88E1112,
611                 .phy_id_mask = MARVELL_PHY_ID_MASK,
612                 .name = "Marvell 88E1112",
613                 .features = PHY_GBIT_FEATURES,
614                 .flags = PHY_HAS_INTERRUPT,
615                 .config_init = &m88e1111_config_init,
616                 .config_aneg = &marvell_config_aneg,
617                 .read_status = &genphy_read_status,
618                 .ack_interrupt = &marvell_ack_interrupt,
619                 .config_intr = &marvell_config_intr,
620                 .driver = { .owner = THIS_MODULE },
621         },
622         {
623                 .phy_id = MARVELL_PHY_ID_88E1111,
624                 .phy_id_mask = MARVELL_PHY_ID_MASK,
625                 .name = "Marvell 88E1111",
626                 .features = PHY_GBIT_FEATURES,
627                 .flags = PHY_HAS_INTERRUPT,
628                 .config_init = &m88e1111_config_init,
629                 .config_aneg = &marvell_config_aneg,
630                 .read_status = &marvell_read_status,
631                 .ack_interrupt = &marvell_ack_interrupt,
632                 .config_intr = &marvell_config_intr,
633                 .driver = { .owner = THIS_MODULE },
634         },
635         {
636                 .phy_id = MARVELL_PHY_ID_88E1118,
637                 .phy_id_mask = MARVELL_PHY_ID_MASK,
638                 .name = "Marvell 88E1118",
639                 .features = PHY_GBIT_FEATURES,
640                 .flags = PHY_HAS_INTERRUPT,
641                 .config_init = &m88e1118_config_init,
642                 .config_aneg = &m88e1118_config_aneg,
643                 .read_status = &genphy_read_status,
644                 .ack_interrupt = &marvell_ack_interrupt,
645                 .config_intr = &marvell_config_intr,
646                 .driver = {.owner = THIS_MODULE,},
647         },
648         {
649                 .phy_id = MARVELL_PHY_ID_88E1121R,
650                 .phy_id_mask = MARVELL_PHY_ID_MASK,
651                 .name = "Marvell 88E1121R",
652                 .features = PHY_GBIT_FEATURES,
653                 .flags = PHY_HAS_INTERRUPT,
654                 .config_aneg = &m88e1121_config_aneg,
655                 .read_status = &marvell_read_status,
656                 .ack_interrupt = &marvell_ack_interrupt,
657                 .config_intr = &marvell_config_intr,
658                 .did_interrupt = &m88e1121_did_interrupt,
659                 .driver = { .owner = THIS_MODULE },
660         },
661         {
662                 .phy_id = MARVELL_PHY_ID_88EC048,
663                 .phy_id_mask = MARVELL_PHY_ID_MASK,
664                 .name = "Marvell 88EC048",
665                 .features = PHY_GBIT_FEATURES,
666                 .flags = PHY_HAS_INTERRUPT,
667                 .config_aneg = &m88ec048_config_aneg,
668                 .read_status = &marvell_read_status,
669                 .ack_interrupt = &marvell_ack_interrupt,
670                 .config_intr = &marvell_config_intr,
671                 .did_interrupt = &m88e1121_did_interrupt,
672                 .driver = { .owner = THIS_MODULE },
673         },
674         {
675                 .phy_id = MARVELL_PHY_ID_88E1145,
676                 .phy_id_mask = MARVELL_PHY_ID_MASK,
677                 .name = "Marvell 88E1145",
678                 .features = PHY_GBIT_FEATURES,
679                 .flags = PHY_HAS_INTERRUPT,
680                 .config_init = &m88e1145_config_init,
681                 .config_aneg = &marvell_config_aneg,
682                 .read_status = &genphy_read_status,
683                 .ack_interrupt = &marvell_ack_interrupt,
684                 .config_intr = &marvell_config_intr,
685                 .driver = { .owner = THIS_MODULE },
686         },
687         {
688                 .phy_id = MARVELL_PHY_ID_88E1240,
689                 .phy_id_mask = MARVELL_PHY_ID_MASK,
690                 .name = "Marvell 88E1240",
691                 .features = PHY_GBIT_FEATURES,
692                 .flags = PHY_HAS_INTERRUPT,
693                 .config_init = &m88e1111_config_init,
694                 .config_aneg = &marvell_config_aneg,
695                 .read_status = &genphy_read_status,
696                 .ack_interrupt = &marvell_ack_interrupt,
697                 .config_intr = &marvell_config_intr,
698                 .driver = { .owner = THIS_MODULE },
699         },
700 };
701
702 static int __init marvell_init(void)
703 {
704         int ret;
705         int i;
706
707         for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) {
708                 ret = phy_driver_register(&marvell_drivers[i]);
709
710                 if (ret) {
711                         while (i-- > 0)
712                                 phy_driver_unregister(&marvell_drivers[i]);
713                         return ret;
714                 }
715         }
716
717         return 0;
718 }
719
720 static void __exit marvell_exit(void)
721 {
722         int i;
723
724         for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++)
725                 phy_driver_unregister(&marvell_drivers[i]);
726 }
727
728 module_init(marvell_init);
729 module_exit(marvell_exit);
730
731 static struct mdio_device_id __maybe_unused marvell_tbl[] = {
732         { 0x01410c60, 0xfffffff0 },
733         { 0x01410c90, 0xfffffff0 },
734         { 0x01410cc0, 0xfffffff0 },
735         { 0x01410e10, 0xfffffff0 },
736         { 0x01410cb0, 0xfffffff0 },
737         { 0x01410cd0, 0xfffffff0 },
738         { 0x01410e30, 0xfffffff0 },
739         { 0x01410e90, 0xfffffff0 },
740         { }
741 };
742
743 MODULE_DEVICE_TABLE(mdio, marvell_tbl);