1/* 2 * drivers/net/ibm_emac/ibm_emac_phy.c 3 * 4 * Driver for PowerPC 4xx on-chip ethernet controller, PHY support. 5 * Borrowed from sungem_phy.c, though I only kept the generic MII 6 * driver for now. 7 * 8 * This file should be shared with other drivers or eventually 9 * merged as the "low level" part of miilib 10 * 11 * (c) 2003, Benjamin Herrenscmidt (benh@kernel.crashing.org) 12 * (c) 2004-2005, Eugene Surovegin <ebs@ebshome.net> 13 * 14 */ 15#include <linux/module.h> 16#include <linux/kernel.h> 17#include <linux/types.h> 18#include <linux/netdevice.h> 19#include <linux/mii.h> 20#include <linux/ethtool.h> 21#include <linux/delay.h> 22 23#include <asm/ocp.h> 24 25#include "ibm_emac_core.h" 26#include "ibm_emac_phy.h" 27 28static inline int phy_read(struct mii_phy *phy, int reg) 29{ 30 return phy->mdio_read(phy->dev, phy->address, reg); 31} 32 33static inline void phy_write(struct mii_phy *phy, int reg, int val) 34{ 35 phy->mdio_write(phy->dev, phy->address, reg, val); 36} 37 38/* 39 * polls MII_BMCR until BMCR_RESET bit clears or operation times out. 40 * 41 * returns: 42 * >= 0 => success, value in BMCR returned to caller 43 * -EBUSY => failure, RESET bit never cleared 44 * otherwise => failure, lower level PHY read failed 45 */ 46static int mii_spin_reset_complete(struct mii_phy *phy) 47{ 48 int val; 49 int limit = 10000; 50 51 while (limit--) { 52 val = phy_read(phy, MII_BMCR); 53 if (val >= 0 && !(val & BMCR_RESET)) 54 return val; /* success */ 55 udelay(10); 56 } 57 if (val & BMCR_RESET) 58 val = -EBUSY; 59 60 if (net_ratelimit()) 61 printk(KERN_ERR "emac%d: PHY reset timeout (%d)\n", 62 ((struct ocp_enet_private *)phy->dev->priv)->def->index, 63 val); 64 return val; 65} 66 67int mii_reset_phy(struct mii_phy *phy) 68{ 69 int val; 70 71 val = phy_read(phy, MII_BMCR); 72 val &= ~BMCR_ISOLATE; 73 val |= BMCR_RESET; 74 phy_write(phy, MII_BMCR, val); 75 76 udelay(300); 77 78 val = mii_spin_reset_complete(phy); 79 if (val >= 0 && (val & BMCR_ISOLATE)) 80 phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE); 81 82 return val < 0; 83} 84 85static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise) 86{ 87 int ctl, adv; 88 89 phy->autoneg = AUTONEG_ENABLE; 90 phy->speed = SPEED_10; 91 phy->duplex = DUPLEX_HALF; 92 phy->pause = phy->asym_pause = 0; 93 phy->advertising = advertise; 94 95 /* Setup standard advertise */ 96 adv = phy_read(phy, MII_ADVERTISE); 97 if (adv < 0) 98 return adv; 99 adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | 100 ADVERTISE_PAUSE_ASYM); 101 if (advertise & ADVERTISED_10baseT_Half) 102 adv |= ADVERTISE_10HALF; 103 if (advertise & ADVERTISED_10baseT_Full) 104 adv |= ADVERTISE_10FULL; 105 if (advertise & ADVERTISED_100baseT_Half) 106 adv |= ADVERTISE_100HALF; 107 if (advertise & ADVERTISED_100baseT_Full) 108 adv |= ADVERTISE_100FULL; 109 if (advertise & ADVERTISED_Pause) 110 adv |= ADVERTISE_PAUSE_CAP; 111 if (advertise & ADVERTISED_Asym_Pause) 112 adv |= ADVERTISE_PAUSE_ASYM; 113 phy_write(phy, MII_ADVERTISE, adv); 114 115 if (phy->features & 116 (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) { 117 adv = phy_read(phy, MII_CTRL1000); 118 if (adv < 0) 119 return adv; 120 adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); 121 if (advertise & ADVERTISED_1000baseT_Full) 122 adv |= ADVERTISE_1000FULL; 123 if (advertise & ADVERTISED_1000baseT_Half) 124 adv |= ADVERTISE_1000HALF; 125 phy_write(phy, MII_CTRL1000, adv); 126 } 127 128 /* Start/Restart aneg */ 129 /* on some PHYs (e.g. National DP83843) a write to MII_ADVERTISE 130 * causes BMCR_RESET to be set on the next read of MII_BMCR, which 131 * if not checked for causes the PHY to be reset below */ 132 ctl = mii_spin_reset_complete(phy); 133 if (ctl < 0) 134 return ctl; 135 136 ctl |= BMCR_ANENABLE | BMCR_ANRESTART; 137 phy_write(phy, MII_BMCR, ctl); 138 139 return 0; 140} 141 142static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd) 143{ 144 int ctl; 145 146 phy->autoneg = AUTONEG_DISABLE; 147 phy->speed = speed; 148 phy->duplex = fd; 149 phy->pause = phy->asym_pause = 0; 150 151 /* First reset the PHY */ 152 mii_reset_phy(phy); 153 154 ctl = phy_read(phy, MII_BMCR); 155 if (ctl < 0) 156 return ctl; 157 ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE | BMCR_SPEED1000); 158 159 /* Select speed & duplex */ 160 switch (speed) { 161 case SPEED_10: 162 break; 163 case SPEED_100: 164 ctl |= BMCR_SPEED100; 165 break; 166 case SPEED_1000: 167 ctl |= BMCR_SPEED1000; 168 break; 169 default: 170 return -EINVAL; 171 } 172 if (fd == DUPLEX_FULL) 173 ctl |= BMCR_FULLDPLX; 174 phy_write(phy, MII_BMCR, ctl); 175 176 return 0; 177} 178 179static int genmii_poll_link(struct mii_phy *phy) 180{ 181 int status; 182 183 /* Clear latched value with dummy read */ 184 phy_read(phy, MII_BMSR); 185 status = phy_read(phy, MII_BMSR); 186 if (status < 0 || (status & BMSR_LSTATUS) == 0) 187 return 0; 188 if (phy->autoneg == AUTONEG_ENABLE && !(status & BMSR_ANEGCOMPLETE)) 189 return 0; 190 return 1; 191} 192 193static int genmii_read_link(struct mii_phy *phy) 194{ 195 if (phy->autoneg == AUTONEG_ENABLE) { 196 int glpa = 0; 197 int lpa = phy_read(phy, MII_LPA) & phy_read(phy, MII_ADVERTISE); 198 if (lpa < 0) 199 return lpa; 200 201 if (phy->features & 202 (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) { 203 int adv = phy_read(phy, MII_CTRL1000); 204 glpa = phy_read(phy, MII_STAT1000); 205 206 if (glpa < 0 || adv < 0) 207 return adv; 208 209 glpa &= adv << 2; 210 } 211 212 phy->speed = SPEED_10; 213 phy->duplex = DUPLEX_HALF; 214 phy->pause = phy->asym_pause = 0; 215 216 if (glpa & (LPA_1000FULL | LPA_1000HALF)) { 217 phy->speed = SPEED_1000; 218 if (glpa & LPA_1000FULL) 219 phy->duplex = DUPLEX_FULL; 220 } else if (lpa & (LPA_100FULL | LPA_100HALF)) { 221 phy->speed = SPEED_100; 222 if (lpa & LPA_100FULL) 223 phy->duplex = DUPLEX_FULL; 224 } else if (lpa & LPA_10FULL) 225 phy->duplex = DUPLEX_FULL; 226 227 if (phy->duplex == DUPLEX_FULL) { 228 phy->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; 229 phy->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; 230 } 231 } else { 232 int bmcr = phy_read(phy, MII_BMCR); 233 if (bmcr < 0) 234 return bmcr; 235 236 if (bmcr & BMCR_FULLDPLX) 237 phy->duplex = DUPLEX_FULL; 238 else 239 phy->duplex = DUPLEX_HALF; 240 if (bmcr & BMCR_SPEED1000) 241 phy->speed = SPEED_1000; 242 else if (bmcr & BMCR_SPEED100) 243 phy->speed = SPEED_100; 244 else 245 phy->speed = SPEED_10; 246 247 phy->pause = phy->asym_pause = 0; 248 } 249 return 0; 250} 251 252/* Generic implementation for most 10/100/1000 PHYs */ 253static struct mii_phy_ops generic_phy_ops = { 254 .setup_aneg = genmii_setup_aneg, 255 .setup_forced = genmii_setup_forced, 256 .poll_link = genmii_poll_link, 257 .read_link = genmii_read_link 258}; 259 260static struct mii_phy_def genmii_phy_def = { 261 .phy_id = 0x00000000, 262 .phy_id_mask = 0x00000000, 263 .name = "Generic MII", 264 .ops = &generic_phy_ops 265}; 266 267/* CIS8201 */ 268#define MII_CIS8201_10BTCSR 0x16 269#define TENBTCSR_ECHO_DISABLE 0x2000 270#define MII_CIS8201_EPCR 0x17 271#define EPCR_MODE_MASK 0x3000 272#define EPCR_GMII_MODE 0x0000 273#define EPCR_RGMII_MODE 0x1000 274#define EPCR_TBI_MODE 0x2000 275#define EPCR_RTBI_MODE 0x3000 276#define MII_CIS8201_ACSR 0x1c 277#define ACSR_PIN_PRIO_SELECT 0x0004 278 279static int cis8201_init(struct mii_phy *phy) 280{ 281 int epcr; 282 283 epcr = phy_read(phy, MII_CIS8201_EPCR); 284 if (epcr < 0) 285 return epcr; 286 287 epcr &= ~EPCR_MODE_MASK; 288 289 switch (phy->mode) { 290 case PHY_MODE_TBI: 291 epcr |= EPCR_TBI_MODE; 292 break; 293 case PHY_MODE_RTBI: 294 epcr |= EPCR_RTBI_MODE; 295 break; 296 case PHY_MODE_GMII: 297 epcr |= EPCR_GMII_MODE; 298 break; 299 case PHY_MODE_RGMII: 300 default: 301 epcr |= EPCR_RGMII_MODE; 302 } 303 304 phy_write(phy, MII_CIS8201_EPCR, epcr); 305 306 /* MII regs override strap pins */ 307 phy_write(phy, MII_CIS8201_ACSR, 308 phy_read(phy, MII_CIS8201_ACSR) | ACSR_PIN_PRIO_SELECT); 309 310 /* Disable TX_EN -> CRS echo mode, otherwise 10/HDX doesn't work */ 311 phy_write(phy, MII_CIS8201_10BTCSR, 312 phy_read(phy, MII_CIS8201_10BTCSR) | TENBTCSR_ECHO_DISABLE); 313 314 return 0; 315} 316 317static struct mii_phy_ops cis8201_phy_ops = { 318 .init = cis8201_init, 319 .setup_aneg = genmii_setup_aneg, 320 .setup_forced = genmii_setup_forced, 321 .poll_link = genmii_poll_link, 322 .read_link = genmii_read_link 323}; 324 325static struct mii_phy_def cis8201_phy_def = { 326 .phy_id = 0x000fc410, 327 .phy_id_mask = 0x000ffff0, 328 .name = "CIS8201 Gigabit Ethernet", 329 .ops = &cis8201_phy_ops 330}; 331 332static struct mii_phy_def *mii_phy_table[] = { 333 &cis8201_phy_def, 334 &genmii_phy_def, 335 NULL 336}; 337 338int mii_phy_probe(struct mii_phy *phy, int address) 339{ 340 struct mii_phy_def *def; 341 int i; 342 int id; 343 344 phy->autoneg = AUTONEG_DISABLE; 345 phy->advertising = 0; 346 phy->address = address; 347 phy->speed = SPEED_10; 348 phy->duplex = DUPLEX_HALF; 349 phy->pause = phy->asym_pause = 0; 350 351 /* Take PHY out of isolate mode and reset it. */ 352 if (mii_reset_phy(phy)) 353 return -ENODEV; 354 355 /* Read ID and find matching entry */ 356 id = (phy_read(phy, MII_PHYSID1) << 16) | phy_read(phy, MII_PHYSID2); 357 if (id < 0) 358 return -ENODEV; 359 for (i = 0; (def = mii_phy_table[i]) != NULL; i++) 360 if ((id & def->phy_id_mask) == def->phy_id) 361 break; 362 /* Should never be NULL (we have a generic entry), but... */ 363 if (!def) 364 return -ENODEV; 365 366 phy->def = def; 367 368 /* Determine PHY features if needed */ 369 phy->features = def->features; 370 if (!phy->features) { 371 u16 bmsr = phy_read(phy, MII_BMSR); 372 if (bmsr & BMSR_ANEGCAPABLE) 373 phy->features |= SUPPORTED_Autoneg; 374 if (bmsr & BMSR_10HALF) 375 phy->features |= SUPPORTED_10baseT_Half; 376 if (bmsr & BMSR_10FULL) 377 phy->features |= SUPPORTED_10baseT_Full; 378 if (bmsr & BMSR_100HALF) 379 phy->features |= SUPPORTED_100baseT_Half; 380 if (bmsr & BMSR_100FULL) 381 phy->features |= SUPPORTED_100baseT_Full; 382 if (bmsr & BMSR_ESTATEN) { 383 u16 esr = phy_read(phy, MII_ESTATUS); 384 if (esr & ESTATUS_1000_TFULL) 385 phy->features |= SUPPORTED_1000baseT_Full; 386 if (esr & ESTATUS_1000_THALF) 387 phy->features |= SUPPORTED_1000baseT_Half; 388 } 389 phy->features |= SUPPORTED_MII; 390 } 391 392 /* Setup default advertising */ 393 phy->advertising = phy->features; 394 395 return 0; 396} 397 398MODULE_LICENSE("GPL"); 399