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 m88e1145_config_init(struct phy_device *phydev) 231 { 232 int err; 233 234 /* Take care of errata E0 & E1 */ 235 err = phy_write(phydev, 0x1d, 0x001b); 236 if (err < 0) 237 return err; 238 239 err = phy_write(phydev, 0x1e, 0x418f); 240 if (err < 0) 241 return err; 242 243 err = phy_write(phydev, 0x1d, 0x0016); 244 if (err < 0) 245 return err; 246 247 err = phy_write(phydev, 0x1e, 0xa2da); 248 if (err < 0) 249 return err; 250 251 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { 252 int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR); 253 if (temp < 0) 254 return temp; 255 256 temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY); 257 258 err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp); 259 if (err < 0) 260 return err; 261 262 if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) { 263 err = phy_write(phydev, 0x1d, 0x0012); 264 if (err < 0) 265 return err; 266 267 temp = phy_read(phydev, 0x1e); 268 if (temp < 0) 269 return temp; 270 271 temp &= 0xf03f; 272 temp |= 2 << 9; /* 36 ohm */ 273 temp |= 2 << 6; /* 39 ohm */ 274 275 err = phy_write(phydev, 0x1e, temp); 276 if (err < 0) 277 return err; 278 279 err = phy_write(phydev, 0x1d, 0x3); 280 if (err < 0) 281 return err; 282 283 err = phy_write(phydev, 0x1e, 0x8000); 284 if (err < 0) 285 return err; 286 } 287 } 288 289 return 0; 290 } 291 292 /* marvell_read_status 293 * 294 * Generic status code does not detect Fiber correctly! 295 * Description: 296 * Check the link, then figure out the current state 297 * by comparing what we advertise with what the link partner 298 * advertises. Start by checking the gigabit possibilities, 299 * then move on to 10/100. 300 */ 301 static int marvell_read_status(struct phy_device *phydev) 302 { 303 int adv; 304 int err; 305 int lpa; 306 int status = 0; 307 308 /* Update the link, but return if there 309 * was an error */ 310 err = genphy_update_link(phydev); 311 if (err) 312 return err; 313 314 if (AUTONEG_ENABLE == phydev->autoneg) { 315 status = phy_read(phydev, MII_M1011_PHY_STATUS); 316 if (status < 0) 317 return status; 318 319 lpa = phy_read(phydev, MII_LPA); 320 if (lpa < 0) 321 return lpa; 322 323 adv = phy_read(phydev, MII_ADVERTISE); 324 if (adv < 0) 325 return adv; 326 327 lpa &= adv; 328 329 if (status & MII_M1011_PHY_STATUS_FULLDUPLEX) 330 phydev->duplex = DUPLEX_FULL; 331 else 332 phydev->duplex = DUPLEX_HALF; 333 334 status = status & MII_M1011_PHY_STATUS_SPD_MASK; 335 phydev->pause = phydev->asym_pause = 0; 336 337 switch (status) { 338 case MII_M1011_PHY_STATUS_1000: 339 phydev->speed = SPEED_1000; 340 break; 341 342 case MII_M1011_PHY_STATUS_100: 343 phydev->speed = SPEED_100; 344 break; 345 346 default: 347 phydev->speed = SPEED_10; 348 break; 349 } 350 351 if (phydev->duplex == DUPLEX_FULL) { 352 phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; 353 phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; 354 } 355 } else { 356 int bmcr = phy_read(phydev, MII_BMCR); 357 358 if (bmcr < 0) 359 return bmcr; 360 361 if (bmcr & BMCR_FULLDPLX) 362 phydev->duplex = DUPLEX_FULL; 363 else 364 phydev->duplex = DUPLEX_HALF; 365 366 if (bmcr & BMCR_SPEED1000) 367 phydev->speed = SPEED_1000; 368 else if (bmcr & BMCR_SPEED100) 369 phydev->speed = SPEED_100; 370 else 371 phydev->speed = SPEED_10; 372 373 phydev->pause = phydev->asym_pause = 0; 374 } 375 376 return 0; 377 } 378 379 static struct phy_driver marvell_drivers[] = { 380 { 381 .phy_id = 0x01410c60, 382 .phy_id_mask = 0xfffffff0, 383 .name = "Marvell 88E1101", 384 .features = PHY_GBIT_FEATURES, 385 .flags = PHY_HAS_INTERRUPT, 386 .config_aneg = &marvell_config_aneg, 387 .read_status = &genphy_read_status, 388 .ack_interrupt = &marvell_ack_interrupt, 389 .config_intr = &marvell_config_intr, 390 .driver = { .owner = THIS_MODULE }, 391 }, 392 { 393 .phy_id = 0x01410c90, 394 .phy_id_mask = 0xfffffff0, 395 .name = "Marvell 88E1112", 396 .features = PHY_GBIT_FEATURES, 397 .flags = PHY_HAS_INTERRUPT, 398 .config_init = &m88e1111_config_init, 399 .config_aneg = &marvell_config_aneg, 400 .read_status = &genphy_read_status, 401 .ack_interrupt = &marvell_ack_interrupt, 402 .config_intr = &marvell_config_intr, 403 .driver = { .owner = THIS_MODULE }, 404 }, 405 { 406 .phy_id = 0x01410cc0, 407 .phy_id_mask = 0xfffffff0, 408 .name = "Marvell 88E1111", 409 .features = PHY_GBIT_FEATURES, 410 .flags = PHY_HAS_INTERRUPT, 411 .config_init = &m88e1111_config_init, 412 .config_aneg = &marvell_config_aneg, 413 .read_status = &marvell_read_status, 414 .ack_interrupt = &marvell_ack_interrupt, 415 .config_intr = &marvell_config_intr, 416 .driver = { .owner = THIS_MODULE }, 417 }, 418 { 419 .phy_id = 0x01410cd0, 420 .phy_id_mask = 0xfffffff0, 421 .name = "Marvell 88E1145", 422 .features = PHY_GBIT_FEATURES, 423 .flags = PHY_HAS_INTERRUPT, 424 .config_init = &m88e1145_config_init, 425 .config_aneg = &marvell_config_aneg, 426 .read_status = &genphy_read_status, 427 .ack_interrupt = &marvell_ack_interrupt, 428 .config_intr = &marvell_config_intr, 429 .driver = { .owner = THIS_MODULE }, 430 }, 431 { 432 .phy_id = 0x01410e30, 433 .phy_id_mask = 0xfffffff0, 434 .name = "Marvell 88E1240", 435 .features = PHY_GBIT_FEATURES, 436 .flags = PHY_HAS_INTERRUPT, 437 .config_init = &m88e1111_config_init, 438 .config_aneg = &marvell_config_aneg, 439 .read_status = &genphy_read_status, 440 .ack_interrupt = &marvell_ack_interrupt, 441 .config_intr = &marvell_config_intr, 442 .driver = { .owner = THIS_MODULE }, 443 }, 444 }; 445 446 static int __init marvell_init(void) 447 { 448 int ret; 449 int i; 450 451 for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) { 452 ret = phy_driver_register(&marvell_drivers[i]); 453 454 if (ret) { 455 while (i-- > 0) 456 phy_driver_unregister(&marvell_drivers[i]); 457 return ret; 458 } 459 } 460 461 return 0; 462 } 463 464 static void __exit marvell_exit(void) 465 { 466 int i; 467 468 for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) 469 phy_driver_unregister(&marvell_drivers[i]); 470 } 471 472 module_init(marvell_init); 473 module_exit(marvell_exit); 474