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/slab.h> 21 #include <linux/interrupt.h> 22 #include <linux/init.h> 23 #include <linux/delay.h> 24 #include <linux/netdevice.h> 25 #include <linux/etherdevice.h> 26 #include <linux/skbuff.h> 27 #include <linux/spinlock.h> 28 #include <linux/mm.h> 29 #include <linux/module.h> 30 #include <linux/mii.h> 31 #include <linux/ethtool.h> 32 #include <linux/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 M1145_DEV_FLAGS_RESISTANCE 0x00000001 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_FIBER_COPPER_AUTO 0x8000 67 #define MII_M1111_HWCFG_FIBER_COPPER_RES 0x2000 68 69 #define MII_M1111_COPPER 0 70 #define MII_M1111_FIBER 1 71 72 #define MII_M1011_PHY_STATUS 0x11 73 #define MII_M1011_PHY_STATUS_1000 0x8000 74 #define MII_M1011_PHY_STATUS_100 0x4000 75 #define MII_M1011_PHY_STATUS_SPD_MASK 0xc000 76 #define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000 77 #define MII_M1011_PHY_STATUS_RESOLVED 0x0800 78 #define MII_M1011_PHY_STATUS_LINK 0x0400 79 80 81 MODULE_DESCRIPTION("Marvell PHY driver"); 82 MODULE_AUTHOR("Andy Fleming"); 83 MODULE_LICENSE("GPL"); 84 85 static int marvell_ack_interrupt(struct phy_device *phydev) 86 { 87 int err; 88 89 /* Clear the interrupts by reading the reg */ 90 err = phy_read(phydev, MII_M1011_IEVENT); 91 92 if (err < 0) 93 return err; 94 95 return 0; 96 } 97 98 static int marvell_config_intr(struct phy_device *phydev) 99 { 100 int err; 101 102 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 103 err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT); 104 else 105 err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); 106 107 return err; 108 } 109 110 static int marvell_config_aneg(struct phy_device *phydev) 111 { 112 int err; 113 114 /* The Marvell PHY has an errata which requires 115 * that certain registers get written in order 116 * to restart autonegotiation */ 117 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 118 119 if (err < 0) 120 return err; 121 122 err = phy_write(phydev, 0x1d, 0x1f); 123 if (err < 0) 124 return err; 125 126 err = phy_write(phydev, 0x1e, 0x200c); 127 if (err < 0) 128 return err; 129 130 err = phy_write(phydev, 0x1d, 0x5); 131 if (err < 0) 132 return err; 133 134 err = phy_write(phydev, 0x1e, 0); 135 if (err < 0) 136 return err; 137 138 err = phy_write(phydev, 0x1e, 0x100); 139 if (err < 0) 140 return err; 141 142 err = phy_write(phydev, MII_M1011_PHY_SCR, 143 MII_M1011_PHY_SCR_AUTO_CROSS); 144 if (err < 0) 145 return err; 146 147 err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL, 148 MII_M1111_PHY_LED_DIRECT); 149 if (err < 0) 150 return err; 151 152 err = genphy_config_aneg(phydev); 153 154 return err; 155 } 156 157 static int m88e1111_config_init(struct phy_device *phydev) 158 { 159 int err; 160 int temp; 161 162 /* Enable Fiber/Copper auto selection */ 163 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 164 temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO; 165 phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 166 167 temp = phy_read(phydev, MII_BMCR); 168 temp |= BMCR_RESET; 169 phy_write(phydev, MII_BMCR, temp); 170 171 if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 172 (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || 173 (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || 174 (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 175 176 temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); 177 if (temp < 0) 178 return temp; 179 180 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { 181 temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); 182 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 183 temp &= ~MII_M1111_TX_DELAY; 184 temp |= MII_M1111_RX_DELAY; 185 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 186 temp &= ~MII_M1111_RX_DELAY; 187 temp |= MII_M1111_TX_DELAY; 188 } 189 190 err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); 191 if (err < 0) 192 return err; 193 194 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 195 if (temp < 0) 196 return temp; 197 198 temp &= ~(MII_M1111_HWCFG_MODE_MASK); 199 200 if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES) 201 temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII; 202 else 203 temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII; 204 205 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 206 if (err < 0) 207 return err; 208 } 209 210 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { 211 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 212 if (temp < 0) 213 return temp; 214 215 temp &= ~(MII_M1111_HWCFG_MODE_MASK); 216 temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK; 217 218 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 219 if (err < 0) 220 return err; 221 } 222 223 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 224 if (err < 0) 225 return err; 226 227 return 0; 228 } 229 230 static int m88e1118_config_aneg(struct phy_device *phydev) 231 { 232 int err; 233 234 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 235 if (err < 0) 236 return err; 237 238 err = phy_write(phydev, MII_M1011_PHY_SCR, 239 MII_M1011_PHY_SCR_AUTO_CROSS); 240 if (err < 0) 241 return err; 242 243 err = genphy_config_aneg(phydev); 244 return 0; 245 } 246 247 static int m88e1118_config_init(struct phy_device *phydev) 248 { 249 int err; 250 251 /* Change address */ 252 err = phy_write(phydev, 0x16, 0x0002); 253 if (err < 0) 254 return err; 255 256 /* Enable 1000 Mbit */ 257 err = phy_write(phydev, 0x15, 0x1070); 258 if (err < 0) 259 return err; 260 261 /* Change address */ 262 err = phy_write(phydev, 0x16, 0x0003); 263 if (err < 0) 264 return err; 265 266 /* Adjust LED Control */ 267 err = phy_write(phydev, 0x10, 0x021e); 268 if (err < 0) 269 return err; 270 271 /* Reset address */ 272 err = phy_write(phydev, 0x16, 0x0); 273 if (err < 0) 274 return err; 275 276 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 277 if (err < 0) 278 return err; 279 280 return 0; 281 } 282 283 static int m88e1145_config_init(struct phy_device *phydev) 284 { 285 int err; 286 287 /* Take care of errata E0 & E1 */ 288 err = phy_write(phydev, 0x1d, 0x001b); 289 if (err < 0) 290 return err; 291 292 err = phy_write(phydev, 0x1e, 0x418f); 293 if (err < 0) 294 return err; 295 296 err = phy_write(phydev, 0x1d, 0x0016); 297 if (err < 0) 298 return err; 299 300 err = phy_write(phydev, 0x1e, 0xa2da); 301 if (err < 0) 302 return err; 303 304 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { 305 int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR); 306 if (temp < 0) 307 return temp; 308 309 temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY); 310 311 err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp); 312 if (err < 0) 313 return err; 314 315 if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) { 316 err = phy_write(phydev, 0x1d, 0x0012); 317 if (err < 0) 318 return err; 319 320 temp = phy_read(phydev, 0x1e); 321 if (temp < 0) 322 return temp; 323 324 temp &= 0xf03f; 325 temp |= 2 << 9; /* 36 ohm */ 326 temp |= 2 << 6; /* 39 ohm */ 327 328 err = phy_write(phydev, 0x1e, temp); 329 if (err < 0) 330 return err; 331 332 err = phy_write(phydev, 0x1d, 0x3); 333 if (err < 0) 334 return err; 335 336 err = phy_write(phydev, 0x1e, 0x8000); 337 if (err < 0) 338 return err; 339 } 340 } 341 342 return 0; 343 } 344 345 /* marvell_read_status 346 * 347 * Generic status code does not detect Fiber correctly! 348 * Description: 349 * Check the link, then figure out the current state 350 * by comparing what we advertise with what the link partner 351 * advertises. Start by checking the gigabit possibilities, 352 * then move on to 10/100. 353 */ 354 static int marvell_read_status(struct phy_device *phydev) 355 { 356 int adv; 357 int err; 358 int lpa; 359 int status = 0; 360 361 /* Update the link, but return if there 362 * was an error */ 363 err = genphy_update_link(phydev); 364 if (err) 365 return err; 366 367 if (AUTONEG_ENABLE == phydev->autoneg) { 368 status = phy_read(phydev, MII_M1011_PHY_STATUS); 369 if (status < 0) 370 return status; 371 372 lpa = phy_read(phydev, MII_LPA); 373 if (lpa < 0) 374 return lpa; 375 376 adv = phy_read(phydev, MII_ADVERTISE); 377 if (adv < 0) 378 return adv; 379 380 lpa &= adv; 381 382 if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) 383 phydev->duplex = DUPLEX_FULL; 384 else 385 phydev->duplex = DUPLEX_HALF; 386 387 status = status & MII_M1011_PHY_STATUS_SPD_MASK; 388 phydev->pause = phydev->asym_pause = 0; 389 390 switch (status) { 391 case MII_M1011_PHY_STATUS_1000: 392 phydev->speed = SPEED_1000; 393 break; 394 395 case MII_M1011_PHY_STATUS_100: 396 phydev->speed = SPEED_100; 397 break; 398 399 default: 400 phydev->speed = SPEED_10; 401 break; 402 } 403 404 if (phydev->duplex == DUPLEX_FULL) { 405 phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; 406 phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; 407 } 408 } else { 409 int bmcr = phy_read(phydev, MII_BMCR); 410 411 if (bmcr < 0) 412 return bmcr; 413 414 if (bmcr & BMCR_FULLDPLX) 415 phydev->duplex = DUPLEX_FULL; 416 else 417 phydev->duplex = DUPLEX_HALF; 418 419 if (bmcr & BMCR_SPEED1000) 420 phydev->speed = SPEED_1000; 421 else if (bmcr & BMCR_SPEED100) 422 phydev->speed = SPEED_100; 423 else 424 phydev->speed = SPEED_10; 425 426 phydev->pause = phydev->asym_pause = 0; 427 } 428 429 return 0; 430 } 431 432 static struct phy_driver marvell_drivers[] = { 433 { 434 .phy_id = 0x01410c60, 435 .phy_id_mask = 0xfffffff0, 436 .name = "Marvell 88E1101", 437 .features = PHY_GBIT_FEATURES, 438 .flags = PHY_HAS_INTERRUPT, 439 .config_aneg = &marvell_config_aneg, 440 .read_status = &genphy_read_status, 441 .ack_interrupt = &marvell_ack_interrupt, 442 .config_intr = &marvell_config_intr, 443 .driver = { .owner = THIS_MODULE }, 444 }, 445 { 446 .phy_id = 0x01410c90, 447 .phy_id_mask = 0xfffffff0, 448 .name = "Marvell 88E1112", 449 .features = PHY_GBIT_FEATURES, 450 .flags = PHY_HAS_INTERRUPT, 451 .config_init = &m88e1111_config_init, 452 .config_aneg = &marvell_config_aneg, 453 .read_status = &genphy_read_status, 454 .ack_interrupt = &marvell_ack_interrupt, 455 .config_intr = &marvell_config_intr, 456 .driver = { .owner = THIS_MODULE }, 457 }, 458 { 459 .phy_id = 0x01410cc0, 460 .phy_id_mask = 0xfffffff0, 461 .name = "Marvell 88E1111", 462 .features = PHY_GBIT_FEATURES, 463 .flags = PHY_HAS_INTERRUPT, 464 .config_init = &m88e1111_config_init, 465 .config_aneg = &marvell_config_aneg, 466 .read_status = &marvell_read_status, 467 .ack_interrupt = &marvell_ack_interrupt, 468 .config_intr = &marvell_config_intr, 469 .driver = { .owner = THIS_MODULE }, 470 }, 471 { 472 .phy_id = 0x01410e10, 473 .phy_id_mask = 0xfffffff0, 474 .name = "Marvell 88E1118", 475 .features = PHY_GBIT_FEATURES, 476 .flags = PHY_HAS_INTERRUPT, 477 .config_init = &m88e1118_config_init, 478 .config_aneg = &m88e1118_config_aneg, 479 .read_status = &genphy_read_status, 480 .ack_interrupt = &marvell_ack_interrupt, 481 .config_intr = &marvell_config_intr, 482 .driver = {.owner = THIS_MODULE,}, 483 }, 484 { 485 .phy_id = 0x01410cd0, 486 .phy_id_mask = 0xfffffff0, 487 .name = "Marvell 88E1145", 488 .features = PHY_GBIT_FEATURES, 489 .flags = PHY_HAS_INTERRUPT, 490 .config_init = &m88e1145_config_init, 491 .config_aneg = &marvell_config_aneg, 492 .read_status = &genphy_read_status, 493 .ack_interrupt = &marvell_ack_interrupt, 494 .config_intr = &marvell_config_intr, 495 .driver = { .owner = THIS_MODULE }, 496 }, 497 { 498 .phy_id = 0x01410e30, 499 .phy_id_mask = 0xfffffff0, 500 .name = "Marvell 88E1240", 501 .features = PHY_GBIT_FEATURES, 502 .flags = PHY_HAS_INTERRUPT, 503 .config_init = &m88e1111_config_init, 504 .config_aneg = &marvell_config_aneg, 505 .read_status = &genphy_read_status, 506 .ack_interrupt = &marvell_ack_interrupt, 507 .config_intr = &marvell_config_intr, 508 .driver = { .owner = THIS_MODULE }, 509 }, 510 }; 511 512 static int __init marvell_init(void) 513 { 514 int ret; 515 int i; 516 517 for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) { 518 ret = phy_driver_register(&marvell_drivers[i]); 519 520 if (ret) { 521 while (i-- > 0) 522 phy_driver_unregister(&marvell_drivers[i]); 523 return ret; 524 } 525 } 526 527 return 0; 528 } 529 530 static void __exit marvell_exit(void) 531 { 532 int i; 533 534 for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) 535 phy_driver_unregister(&marvell_drivers[i]); 536 } 537 538 module_init(marvell_init); 539 module_exit(marvell_exit); 540