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); 737