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 #define MII_M1111_HWCFG_MODE_MASK 0xf 62 #define MII_M1111_HWCFG_MODE_RGMII 0xb 63 #define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4 64 65 MODULE_DESCRIPTION("Marvell PHY driver"); 66 MODULE_AUTHOR("Andy Fleming"); 67 MODULE_LICENSE("GPL"); 68 69 static int marvell_ack_interrupt(struct phy_device *phydev) 70 { 71 int err; 72 73 /* Clear the interrupts by reading the reg */ 74 err = phy_read(phydev, MII_M1011_IEVENT); 75 76 if (err < 0) 77 return err; 78 79 return 0; 80 } 81 82 static int marvell_config_intr(struct phy_device *phydev) 83 { 84 int err; 85 86 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 87 err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT); 88 else 89 err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); 90 91 return err; 92 } 93 94 static int marvell_config_aneg(struct phy_device *phydev) 95 { 96 int err; 97 98 /* The Marvell PHY has an errata which requires 99 * that certain registers get written in order 100 * to restart autonegotiation */ 101 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 102 103 if (err < 0) 104 return err; 105 106 err = phy_write(phydev, 0x1d, 0x1f); 107 if (err < 0) 108 return err; 109 110 err = phy_write(phydev, 0x1e, 0x200c); 111 if (err < 0) 112 return err; 113 114 err = phy_write(phydev, 0x1d, 0x5); 115 if (err < 0) 116 return err; 117 118 err = phy_write(phydev, 0x1e, 0); 119 if (err < 0) 120 return err; 121 122 err = phy_write(phydev, 0x1e, 0x100); 123 if (err < 0) 124 return err; 125 126 err = phy_write(phydev, MII_M1011_PHY_SCR, 127 MII_M1011_PHY_SCR_AUTO_CROSS); 128 if (err < 0) 129 return err; 130 131 err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL, 132 MII_M1111_PHY_LED_DIRECT); 133 if (err < 0) 134 return err; 135 136 err = genphy_config_aneg(phydev); 137 138 return err; 139 } 140 141 static int m88e1111_config_init(struct phy_device *phydev) 142 { 143 int err; 144 145 if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || 146 (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) { 147 int temp; 148 149 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { 150 temp = phy_read(phydev, MII_M1111_PHY_EXT_CR); 151 if (temp < 0) 152 return temp; 153 154 temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY); 155 156 err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp); 157 if (err < 0) 158 return err; 159 } 160 161 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 162 if (temp < 0) 163 return temp; 164 165 temp &= ~(MII_M1111_HWCFG_MODE_MASK); 166 temp |= MII_M1111_HWCFG_MODE_RGMII; 167 168 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 169 if (err < 0) 170 return err; 171 } 172 173 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { 174 int temp; 175 176 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); 177 if (temp < 0) 178 return temp; 179 180 temp &= ~(MII_M1111_HWCFG_MODE_MASK); 181 temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK; 182 183 err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); 184 if (err < 0) 185 return err; 186 } 187 188 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 189 if (err < 0) 190 return err; 191 192 return 0; 193 } 194 195 static int m88e1145_config_init(struct phy_device *phydev) 196 { 197 int err; 198 199 /* Take care of errata E0 & E1 */ 200 err = phy_write(phydev, 0x1d, 0x001b); 201 if (err < 0) 202 return err; 203 204 err = phy_write(phydev, 0x1e, 0x418f); 205 if (err < 0) 206 return err; 207 208 err = phy_write(phydev, 0x1d, 0x0016); 209 if (err < 0) 210 return err; 211 212 err = phy_write(phydev, 0x1e, 0xa2da); 213 if (err < 0) 214 return err; 215 216 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) { 217 int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR); 218 if (temp < 0) 219 return temp; 220 221 temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY); 222 223 err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp); 224 if (err < 0) 225 return err; 226 227 if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) { 228 err = phy_write(phydev, 0x1d, 0x0012); 229 if (err < 0) 230 return err; 231 232 temp = phy_read(phydev, 0x1e); 233 if (temp < 0) 234 return temp; 235 236 temp &= 0xf03f; 237 temp |= 2 << 9; /* 36 ohm */ 238 temp |= 2 << 6; /* 39 ohm */ 239 240 err = phy_write(phydev, 0x1e, temp); 241 if (err < 0) 242 return err; 243 244 err = phy_write(phydev, 0x1d, 0x3); 245 if (err < 0) 246 return err; 247 248 err = phy_write(phydev, 0x1e, 0x8000); 249 if (err < 0) 250 return err; 251 } 252 } 253 254 return 0; 255 } 256 257 static struct phy_driver marvell_drivers[] = { 258 { 259 .phy_id = 0x01410c60, 260 .phy_id_mask = 0xfffffff0, 261 .name = "Marvell 88E1101", 262 .features = PHY_GBIT_FEATURES, 263 .flags = PHY_HAS_INTERRUPT, 264 .config_aneg = &marvell_config_aneg, 265 .read_status = &genphy_read_status, 266 .ack_interrupt = &marvell_ack_interrupt, 267 .config_intr = &marvell_config_intr, 268 .driver = {.owner = THIS_MODULE,}, 269 }, 270 { 271 .phy_id = 0x01410c90, 272 .phy_id_mask = 0xfffffff0, 273 .name = "Marvell 88E1112", 274 .features = PHY_GBIT_FEATURES, 275 .flags = PHY_HAS_INTERRUPT, 276 .config_init = &m88e1111_config_init, 277 .config_aneg = &marvell_config_aneg, 278 .read_status = &genphy_read_status, 279 .ack_interrupt = &marvell_ack_interrupt, 280 .config_intr = &marvell_config_intr, 281 .driver = {.owner = THIS_MODULE,}, 282 }, 283 { 284 .phy_id = 0x01410cc0, 285 .phy_id_mask = 0xfffffff0, 286 .name = "Marvell 88E1111", 287 .features = PHY_GBIT_FEATURES, 288 .flags = PHY_HAS_INTERRUPT, 289 .config_init = &m88e1111_config_init, 290 .config_aneg = &marvell_config_aneg, 291 .read_status = &genphy_read_status, 292 .ack_interrupt = &marvell_ack_interrupt, 293 .config_intr = &marvell_config_intr, 294 .driver = {.owner = THIS_MODULE,}, 295 }, 296 { 297 .phy_id = 0x01410cd0, 298 .phy_id_mask = 0xfffffff0, 299 .name = "Marvell 88E1145", 300 .features = PHY_GBIT_FEATURES, 301 .flags = PHY_HAS_INTERRUPT, 302 .config_init = &m88e1145_config_init, 303 .config_aneg = &marvell_config_aneg, 304 .read_status = &genphy_read_status, 305 .ack_interrupt = &marvell_ack_interrupt, 306 .config_intr = &marvell_config_intr, 307 .driver = {.owner = THIS_MODULE,}, 308 } 309 }; 310 311 static int __init marvell_init(void) 312 { 313 int ret; 314 int i; 315 316 for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) { 317 ret = phy_driver_register(&marvell_drivers[i]); 318 319 if (ret) { 320 while (i-- > 0) 321 phy_driver_unregister(&marvell_drivers[i]); 322 return ret; 323 } 324 } 325 326 return 0; 327 } 328 329 static void __exit marvell_exit(void) 330 { 331 int i; 332 333 for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) 334 phy_driver_unregister(&marvell_drivers[i]); 335 } 336 337 module_init(marvell_init); 338 module_exit(marvell_exit); 339