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