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 94MODULE_DESCRIPTION("Marvell PHY driver"); 95MODULE_AUTHOR("Andy Fleming"); 96MODULE_LICENSE("GPL"); 97 98static 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 111static 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 123static 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 189static 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 243static 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 268static 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 379static 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 396static 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 435static 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 */ 506static 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 584static 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 596static 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 702static 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 720static 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 728module_init(marvell_init); 729module_exit(marvell_exit); 730 731static struct mdio_device_id 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 743MODULE_DEVICE_TABLE(mdio, marvell_tbl); 744