Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
[linux-3.10.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         mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) &
200                 MII_88E1121_PHY_MSCR_DELAY_MASK;
201
202         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
203                 mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
204                          MII_88E1121_PHY_MSCR_TX_DELAY);
205         else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
206                 mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
207         else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
208                 mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
209
210         err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
211         if (err < 0)
212                 return err;
213
214         phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
215
216         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
217         if (err < 0)
218                 return err;
219
220         err = phy_write(phydev, MII_M1011_PHY_SCR,
221                         MII_M1011_PHY_SCR_AUTO_CROSS);
222         if (err < 0)
223                 return err;
224
225         oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE);
226
227         phy_write(phydev, MII_88E1121_PHY_PAGE, MII_88E1121_PHY_LED_PAGE);
228         phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF);
229         phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
230
231         err = genphy_config_aneg(phydev);
232
233         return err;
234 }
235
236 static int m88ec048_config_aneg(struct phy_device *phydev)
237 {
238         int err, oldpage, mscr;
239
240         oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE);
241
242         err = phy_write(phydev, MII_88E1121_PHY_PAGE,
243                         MII_88E1121_PHY_MSCR_PAGE);
244         if (err < 0)
245                 return err;
246
247         mscr = phy_read(phydev, MII_88EC048_PHY_MSCR1_REG);
248         mscr |= MII_88EC048_PHY_MSCR1_PAD_ODD;
249
250         err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
251         if (err < 0)
252                 return err;
253
254         err = phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage);
255         if (err < 0)
256                 return err;
257
258         return m88e1121_config_aneg(phydev);
259 }
260
261 static int m88e1111_config_init(struct phy_device *phydev)
262 {
263         int err;
264         int temp;
265
266         /* Enable Fiber/Copper auto selection */
267         temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
268         temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO;
269         phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
270
271         temp = phy_read(phydev, MII_BMCR);
272         temp |= BMCR_RESET;
273         phy_write(phydev, MII_BMCR, temp);
274
275         if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
276             (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
277             (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
278             (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
279
280                 temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
281                 if (temp < 0)
282                         return temp;
283
284                 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
285                         temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
286                 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
287                         temp &= ~MII_M1111_TX_DELAY;
288                         temp |= MII_M1111_RX_DELAY;
289                 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
290                         temp &= ~MII_M1111_RX_DELAY;
291                         temp |= MII_M1111_TX_DELAY;
292                 }
293
294                 err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
295                 if (err < 0)
296                         return err;
297
298                 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
299                 if (temp < 0)
300                         return temp;
301
302                 temp &= ~(MII_M1111_HWCFG_MODE_MASK);
303
304                 if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES)
305                         temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII;
306                 else
307                         temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII;
308
309                 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
310                 if (err < 0)
311                         return err;
312         }
313
314         if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
315                 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
316                 if (temp < 0)
317                         return temp;
318
319                 temp &= ~(MII_M1111_HWCFG_MODE_MASK);
320                 temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK;
321                 temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
322
323                 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
324                 if (err < 0)
325                         return err;
326         }
327
328         if (phydev->interface == PHY_INTERFACE_MODE_RTBI) {
329                 temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
330                 if (temp < 0)
331                         return temp;
332                 temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
333                 err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
334                 if (err < 0)
335                         return err;
336
337                 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
338                 if (temp < 0)
339                         return temp;
340                 temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES);
341                 temp |= 0x7 | MII_M1111_HWCFG_FIBER_COPPER_AUTO;
342                 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
343                 if (err < 0)
344                         return err;
345
346                 /* soft reset */
347                 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
348                 if (err < 0)
349                         return err;
350                 do
351                         temp = phy_read(phydev, MII_BMCR);
352                 while (temp & BMCR_RESET);
353
354                 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
355                 if (temp < 0)
356                         return temp;
357                 temp &= ~(MII_M1111_HWCFG_MODE_MASK | MII_M1111_HWCFG_FIBER_COPPER_RES);
358                 temp |= MII_M1111_HWCFG_MODE_COPPER_RTBI | MII_M1111_HWCFG_FIBER_COPPER_AUTO;
359                 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
360                 if (err < 0)
361                         return err;
362         }
363
364
365         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
366         if (err < 0)
367                 return err;
368
369         return 0;
370 }
371
372 static int m88e1118_config_aneg(struct phy_device *phydev)
373 {
374         int err;
375
376         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
377         if (err < 0)
378                 return err;
379
380         err = phy_write(phydev, MII_M1011_PHY_SCR,
381                         MII_M1011_PHY_SCR_AUTO_CROSS);
382         if (err < 0)
383                 return err;
384
385         err = genphy_config_aneg(phydev);
386         return 0;
387 }
388
389 static int m88e1118_config_init(struct phy_device *phydev)
390 {
391         int err;
392
393         /* Change address */
394         err = phy_write(phydev, 0x16, 0x0002);
395         if (err < 0)
396                 return err;
397
398         /* Enable 1000 Mbit */
399         err = phy_write(phydev, 0x15, 0x1070);
400         if (err < 0)
401                 return err;
402
403         /* Change address */
404         err = phy_write(phydev, 0x16, 0x0003);
405         if (err < 0)
406                 return err;
407
408         /* Adjust LED Control */
409         if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS)
410                 err = phy_write(phydev, 0x10, 0x1100);
411         else
412                 err = phy_write(phydev, 0x10, 0x021e);
413         if (err < 0)
414                 return err;
415
416         /* Reset address */
417         err = phy_write(phydev, 0x16, 0x0);
418         if (err < 0)
419                 return err;
420
421         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
422         if (err < 0)
423                 return err;
424
425         return 0;
426 }
427
428 static int m88e1145_config_init(struct phy_device *phydev)
429 {
430         int err;
431
432         /* Take care of errata E0 & E1 */
433         err = phy_write(phydev, 0x1d, 0x001b);
434         if (err < 0)
435                 return err;
436
437         err = phy_write(phydev, 0x1e, 0x418f);
438         if (err < 0)
439                 return err;
440
441         err = phy_write(phydev, 0x1d, 0x0016);
442         if (err < 0)
443                 return err;
444
445         err = phy_write(phydev, 0x1e, 0xa2da);
446         if (err < 0)
447                 return err;
448
449         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
450                 int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR);
451                 if (temp < 0)
452                         return temp;
453
454                 temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY);
455
456                 err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp);
457                 if (err < 0)
458                         return err;
459
460                 if (phydev->dev_flags & MARVELL_PHY_M1145_FLAGS_RESISTANCE) {
461                         err = phy_write(phydev, 0x1d, 0x0012);
462                         if (err < 0)
463                                 return err;
464
465                         temp = phy_read(phydev, 0x1e);
466                         if (temp < 0)
467                                 return temp;
468
469                         temp &= 0xf03f;
470                         temp |= 2 << 9; /* 36 ohm */
471                         temp |= 2 << 6; /* 39 ohm */
472
473                         err = phy_write(phydev, 0x1e, temp);
474                         if (err < 0)
475                                 return err;
476
477                         err = phy_write(phydev, 0x1d, 0x3);
478                         if (err < 0)
479                                 return err;
480
481                         err = phy_write(phydev, 0x1e, 0x8000);
482                         if (err < 0)
483                                 return err;
484                 }
485         }
486
487         return 0;
488 }
489
490 /* marvell_read_status
491  *
492  * Generic status code does not detect Fiber correctly!
493  * Description:
494  *   Check the link, then figure out the current state
495  *   by comparing what we advertise with what the link partner
496  *   advertises.  Start by checking the gigabit possibilities,
497  *   then move on to 10/100.
498  */
499 static int marvell_read_status(struct phy_device *phydev)
500 {
501         int adv;
502         int err;
503         int lpa;
504         int status = 0;
505
506         /* Update the link, but return if there
507          * was an error */
508         err = genphy_update_link(phydev);
509         if (err)
510                 return err;
511
512         if (AUTONEG_ENABLE == phydev->autoneg) {
513                 status = phy_read(phydev, MII_M1011_PHY_STATUS);
514                 if (status < 0)
515                         return status;
516
517                 lpa = phy_read(phydev, MII_LPA);
518                 if (lpa < 0)
519                         return lpa;
520
521                 adv = phy_read(phydev, MII_ADVERTISE);
522                 if (adv < 0)
523                         return adv;
524
525                 lpa &= adv;
526
527                 if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
528                         phydev->duplex = DUPLEX_FULL;
529                 else
530                         phydev->duplex = DUPLEX_HALF;
531
532                 status = status & MII_M1011_PHY_STATUS_SPD_MASK;
533                 phydev->pause = phydev->asym_pause = 0;
534
535                 switch (status) {
536                 case MII_M1011_PHY_STATUS_1000:
537                         phydev->speed = SPEED_1000;
538                         break;
539
540                 case MII_M1011_PHY_STATUS_100:
541                         phydev->speed = SPEED_100;
542                         break;
543
544                 default:
545                         phydev->speed = SPEED_10;
546                         break;
547                 }
548
549                 if (phydev->duplex == DUPLEX_FULL) {
550                         phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
551                         phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
552                 }
553         } else {
554                 int bmcr = phy_read(phydev, MII_BMCR);
555
556                 if (bmcr < 0)
557                         return bmcr;
558
559                 if (bmcr & BMCR_FULLDPLX)
560                         phydev->duplex = DUPLEX_FULL;
561                 else
562                         phydev->duplex = DUPLEX_HALF;
563
564                 if (bmcr & BMCR_SPEED1000)
565                         phydev->speed = SPEED_1000;
566                 else if (bmcr & BMCR_SPEED100)
567                         phydev->speed = SPEED_100;
568                 else
569                         phydev->speed = SPEED_10;
570
571                 phydev->pause = phydev->asym_pause = 0;
572         }
573
574         return 0;
575 }
576
577 static int m88e1121_did_interrupt(struct phy_device *phydev)
578 {
579         int imask;
580
581         imask = phy_read(phydev, MII_M1011_IEVENT);
582
583         if (imask & MII_M1011_IMASK_INIT)
584                 return 1;
585
586         return 0;
587 }
588
589 static struct phy_driver marvell_drivers[] = {
590         {
591                 .phy_id = MARVELL_PHY_ID_88E1101,
592                 .phy_id_mask = MARVELL_PHY_ID_MASK,
593                 .name = "Marvell 88E1101",
594                 .features = PHY_GBIT_FEATURES,
595                 .flags = PHY_HAS_INTERRUPT,
596                 .config_aneg = &marvell_config_aneg,
597                 .read_status = &genphy_read_status,
598                 .ack_interrupt = &marvell_ack_interrupt,
599                 .config_intr = &marvell_config_intr,
600                 .driver = { .owner = THIS_MODULE },
601         },
602         {
603                 .phy_id = MARVELL_PHY_ID_88E1112,
604                 .phy_id_mask = MARVELL_PHY_ID_MASK,
605                 .name = "Marvell 88E1112",
606                 .features = PHY_GBIT_FEATURES,
607                 .flags = PHY_HAS_INTERRUPT,
608                 .config_init = &m88e1111_config_init,
609                 .config_aneg = &marvell_config_aneg,
610                 .read_status = &genphy_read_status,
611                 .ack_interrupt = &marvell_ack_interrupt,
612                 .config_intr = &marvell_config_intr,
613                 .driver = { .owner = THIS_MODULE },
614         },
615         {
616                 .phy_id = MARVELL_PHY_ID_88E1111,
617                 .phy_id_mask = MARVELL_PHY_ID_MASK,
618                 .name = "Marvell 88E1111",
619                 .features = PHY_GBIT_FEATURES,
620                 .flags = PHY_HAS_INTERRUPT,
621                 .config_init = &m88e1111_config_init,
622                 .config_aneg = &marvell_config_aneg,
623                 .read_status = &marvell_read_status,
624                 .ack_interrupt = &marvell_ack_interrupt,
625                 .config_intr = &marvell_config_intr,
626                 .driver = { .owner = THIS_MODULE },
627         },
628         {
629                 .phy_id = MARVELL_PHY_ID_88E1118,
630                 .phy_id_mask = MARVELL_PHY_ID_MASK,
631                 .name = "Marvell 88E1118",
632                 .features = PHY_GBIT_FEATURES,
633                 .flags = PHY_HAS_INTERRUPT,
634                 .config_init = &m88e1118_config_init,
635                 .config_aneg = &m88e1118_config_aneg,
636                 .read_status = &genphy_read_status,
637                 .ack_interrupt = &marvell_ack_interrupt,
638                 .config_intr = &marvell_config_intr,
639                 .driver = {.owner = THIS_MODULE,},
640         },
641         {
642                 .phy_id = MARVELL_PHY_ID_88E1121R,
643                 .phy_id_mask = MARVELL_PHY_ID_MASK,
644                 .name = "Marvell 88E1121R",
645                 .features = PHY_GBIT_FEATURES,
646                 .flags = PHY_HAS_INTERRUPT,
647                 .config_aneg = &m88e1121_config_aneg,
648                 .read_status = &marvell_read_status,
649                 .ack_interrupt = &marvell_ack_interrupt,
650                 .config_intr = &marvell_config_intr,
651                 .did_interrupt = &m88e1121_did_interrupt,
652                 .driver = { .owner = THIS_MODULE },
653         },
654         {
655                 .phy_id = MARVELL_PHY_ID_88EC048,
656                 .phy_id_mask = MARVELL_PHY_ID_MASK,
657                 .name = "Marvell 88EC048",
658                 .features = PHY_GBIT_FEATURES,
659                 .flags = PHY_HAS_INTERRUPT,
660                 .config_aneg = &m88ec048_config_aneg,
661                 .read_status = &marvell_read_status,
662                 .ack_interrupt = &marvell_ack_interrupt,
663                 .config_intr = &marvell_config_intr,
664                 .did_interrupt = &m88e1121_did_interrupt,
665                 .driver = { .owner = THIS_MODULE },
666         },
667         {
668                 .phy_id = MARVELL_PHY_ID_88E1145,
669                 .phy_id_mask = MARVELL_PHY_ID_MASK,
670                 .name = "Marvell 88E1145",
671                 .features = PHY_GBIT_FEATURES,
672                 .flags = PHY_HAS_INTERRUPT,
673                 .config_init = &m88e1145_config_init,
674                 .config_aneg = &marvell_config_aneg,
675                 .read_status = &genphy_read_status,
676                 .ack_interrupt = &marvell_ack_interrupt,
677                 .config_intr = &marvell_config_intr,
678                 .driver = { .owner = THIS_MODULE },
679         },
680         {
681                 .phy_id = MARVELL_PHY_ID_88E1240,
682                 .phy_id_mask = MARVELL_PHY_ID_MASK,
683                 .name = "Marvell 88E1240",
684                 .features = PHY_GBIT_FEATURES,
685                 .flags = PHY_HAS_INTERRUPT,
686                 .config_init = &m88e1111_config_init,
687                 .config_aneg = &marvell_config_aneg,
688                 .read_status = &genphy_read_status,
689                 .ack_interrupt = &marvell_ack_interrupt,
690                 .config_intr = &marvell_config_intr,
691                 .driver = { .owner = THIS_MODULE },
692         },
693 };
694
695 static int __init marvell_init(void)
696 {
697         int ret;
698         int i;
699
700         for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) {
701                 ret = phy_driver_register(&marvell_drivers[i]);
702
703                 if (ret) {
704                         while (i-- > 0)
705                                 phy_driver_unregister(&marvell_drivers[i]);
706                         return ret;
707                 }
708         }
709
710         return 0;
711 }
712
713 static void __exit marvell_exit(void)
714 {
715         int i;
716
717         for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++)
718                 phy_driver_unregister(&marvell_drivers[i]);
719 }
720
721 module_init(marvell_init);
722 module_exit(marvell_exit);
723
724 static struct mdio_device_id marvell_tbl[] = {
725         { 0x01410c60, 0xfffffff0 },
726         { 0x01410c90, 0xfffffff0 },
727         { 0x01410cc0, 0xfffffff0 },
728         { 0x01410e10, 0xfffffff0 },
729         { 0x01410cb0, 0xfffffff0 },
730         { 0x01410cd0, 0xfffffff0 },
731         { 0x01410e30, 0xfffffff0 },
732         { 0x01410e90, 0xfffffff0 },
733         { }
734 };
735
736 MODULE_DEVICE_TABLE(mdio, marvell_tbl);