1 /* 2 * (C) Copyright 2001 3 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 /* 25 * This provides a bit-banged interface to the ethernet MII management 26 * channel. 27 */ 28 29 #include <common.h> 30 #include <miiphy.h> 31 32 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) 33 #include <asm/types.h> 34 #include <linux/list.h> 35 #include <malloc.h> 36 #include <net.h> 37 38 /* local debug macro */ 39 #define MII_DEBUG 40 #undef MII_DEBUG 41 42 #undef debug 43 #ifdef MII_DEBUG 44 #define debug(fmt,args...) printf (fmt ,##args) 45 #else 46 #define debug(fmt,args...) 47 #endif /* MII_DEBUG */ 48 49 struct mii_dev { 50 struct list_head link; 51 char *name; 52 int (*read) (char *devname, unsigned char addr, 53 unsigned char reg, unsigned short *value); 54 int (*write) (char *devname, unsigned char addr, 55 unsigned char reg, unsigned short value); 56 }; 57 58 static struct list_head mii_devs; 59 static struct mii_dev *current_mii; 60 61 /***************************************************************************** 62 * 63 * Initialize global data. Need to be called before any other miiphy routine. 64 */ 65 void miiphy_init () 66 { 67 INIT_LIST_HEAD (&mii_devs); 68 current_mii = NULL; 69 } 70 71 /***************************************************************************** 72 * 73 * Register read and write MII access routines for the device <name>. 74 */ 75 void miiphy_register (char *name, 76 int (*read) (char *devname, unsigned char addr, 77 unsigned char reg, unsigned short *value), 78 int (*write) (char *devname, unsigned char addr, 79 unsigned char reg, unsigned short value)) 80 { 81 struct list_head *entry; 82 struct mii_dev *new_dev; 83 struct mii_dev *miidev; 84 unsigned int name_len; 85 86 /* check if we have unique name */ 87 list_for_each (entry, &mii_devs) { 88 miidev = list_entry (entry, struct mii_dev, link); 89 if (strcmp (miidev->name, name) == 0) { 90 printf ("miiphy_register: non unique device name " 91 "'%s'\n", name); 92 return; 93 } 94 } 95 96 /* allocate memory */ 97 name_len = strlen (name); 98 new_dev = 99 (struct mii_dev *)malloc (sizeof (struct mii_dev) + name_len + 1); 100 101 if (new_dev == NULL) { 102 printf ("miiphy_register: cannot allocate memory for '%s'\n", 103 name); 104 return; 105 } 106 memset (new_dev, 0, sizeof (struct mii_dev) + name_len); 107 108 /* initalize mii_dev struct fields */ 109 INIT_LIST_HEAD (&new_dev->link); 110 new_dev->read = read; 111 new_dev->write = write; 112 new_dev->name = (char *)(new_dev + 1); 113 strncpy (new_dev->name, name, name_len); 114 new_dev->name[name_len] = '\0'; 115 116 debug ("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n", 117 new_dev->name, new_dev->read, new_dev->write); 118 119 /* add it to the list */ 120 list_add_tail (&new_dev->link, &mii_devs); 121 122 if (!current_mii) 123 current_mii = new_dev; 124 } 125 126 int miiphy_set_current_dev (char *devname) 127 { 128 struct list_head *entry; 129 struct mii_dev *dev; 130 131 list_for_each (entry, &mii_devs) { 132 dev = list_entry (entry, struct mii_dev, link); 133 134 if (strcmp (devname, dev->name) == 0) { 135 current_mii = dev; 136 return 0; 137 } 138 } 139 140 printf ("No such device: %s\n", devname); 141 return 1; 142 } 143 144 char *miiphy_get_current_dev () 145 { 146 if (current_mii) 147 return current_mii->name; 148 149 return NULL; 150 } 151 152 /***************************************************************************** 153 * 154 * Read to variable <value> from the PHY attached to device <devname>, 155 * use PHY address <addr> and register <reg>. 156 * 157 * Returns: 158 * 0 on success 159 */ 160 int miiphy_read (char *devname, unsigned char addr, unsigned char reg, 161 unsigned short *value) 162 { 163 struct list_head *entry; 164 struct mii_dev *dev; 165 int found_dev = 0; 166 int read_ret = 0; 167 168 if (!devname) { 169 printf ("NULL device name!\n"); 170 return 1; 171 } 172 173 list_for_each (entry, &mii_devs) { 174 dev = list_entry (entry, struct mii_dev, link); 175 176 if (strcmp (devname, dev->name) == 0) { 177 found_dev = 1; 178 read_ret = dev->read (devname, addr, reg, value); 179 break; 180 } 181 } 182 183 if (found_dev == 0) 184 printf ("No such device: %s\n", devname); 185 186 return ((found_dev) ? read_ret : 1); 187 } 188 189 /***************************************************************************** 190 * 191 * Write <value> to the PHY attached to device <devname>, 192 * use PHY address <addr> and register <reg>. 193 * 194 * Returns: 195 * 0 on success 196 */ 197 int miiphy_write (char *devname, unsigned char addr, unsigned char reg, 198 unsigned short value) 199 { 200 struct list_head *entry; 201 struct mii_dev *dev; 202 int found_dev = 0; 203 int write_ret = 0; 204 205 if (!devname) { 206 printf ("NULL device name!\n"); 207 return 1; 208 } 209 210 list_for_each (entry, &mii_devs) { 211 dev = list_entry (entry, struct mii_dev, link); 212 213 if (strcmp (devname, dev->name) == 0) { 214 found_dev = 1; 215 write_ret = dev->write (devname, addr, reg, value); 216 break; 217 } 218 } 219 220 if (found_dev == 0) 221 printf ("No such device: %s\n", devname); 222 223 return ((found_dev) ? write_ret : 1); 224 } 225 226 /***************************************************************************** 227 * 228 * Print out list of registered MII capable devices. 229 */ 230 void miiphy_listdev (void) 231 { 232 struct list_head *entry; 233 struct mii_dev *dev; 234 235 puts ("MII devices: "); 236 list_for_each (entry, &mii_devs) { 237 dev = list_entry (entry, struct mii_dev, link); 238 printf ("'%s' ", dev->name); 239 } 240 puts ("\n"); 241 242 if (current_mii) 243 printf ("Current device: '%s'\n", current_mii->name); 244 } 245 246 /***************************************************************************** 247 * 248 * Read the OUI, manufacture's model number, and revision number. 249 * 250 * OUI: 22 bits (unsigned int) 251 * Model: 6 bits (unsigned char) 252 * Revision: 4 bits (unsigned char) 253 * 254 * Returns: 255 * 0 on success 256 */ 257 int miiphy_info (char *devname, unsigned char addr, unsigned int *oui, 258 unsigned char *model, unsigned char *rev) 259 { 260 unsigned int reg = 0; 261 unsigned short tmp; 262 263 if (miiphy_read (devname, addr, PHY_PHYIDR2, &tmp) != 0) { 264 #ifdef DEBUG 265 puts ("PHY ID register 2 read failed\n"); 266 #endif 267 return (-1); 268 } 269 reg = tmp; 270 271 #ifdef DEBUG 272 printf ("PHY_PHYIDR2 @ 0x%x = 0x%04x\n", addr, reg); 273 #endif 274 if (reg == 0xFFFF) { 275 /* No physical device present at this address */ 276 return (-1); 277 } 278 279 if (miiphy_read (devname, addr, PHY_PHYIDR1, &tmp) != 0) { 280 #ifdef DEBUG 281 puts ("PHY ID register 1 read failed\n"); 282 #endif 283 return (-1); 284 } 285 reg |= tmp << 16; 286 #ifdef DEBUG 287 printf ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg); 288 #endif 289 *oui = (reg >> 10); 290 *model = (unsigned char)((reg >> 4) & 0x0000003F); 291 *rev = (unsigned char)(reg & 0x0000000F); 292 return (0); 293 } 294 295 /***************************************************************************** 296 * 297 * Reset the PHY. 298 * Returns: 299 * 0 on success 300 */ 301 int miiphy_reset (char *devname, unsigned char addr) 302 { 303 unsigned short reg; 304 int loop_cnt; 305 306 if (miiphy_read (devname, addr, PHY_BMCR, ®) != 0) { 307 #ifdef DEBUG 308 printf ("PHY status read failed\n"); 309 #endif 310 return (-1); 311 } 312 if (miiphy_write (devname, addr, PHY_BMCR, reg | 0x8000) != 0) { 313 #ifdef DEBUG 314 puts ("PHY reset failed\n"); 315 #endif 316 return (-1); 317 } 318 #ifdef CONFIG_PHY_RESET_DELAY 319 udelay (CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */ 320 #endif 321 /* 322 * Poll the control register for the reset bit to go to 0 (it is 323 * auto-clearing). This should happen within 0.5 seconds per the 324 * IEEE spec. 325 */ 326 loop_cnt = 0; 327 reg = 0x8000; 328 while (((reg & 0x8000) != 0) && (loop_cnt++ < 1000000)) { 329 if (miiphy_read (devname, addr, PHY_BMCR, ®) != 0) { 330 # ifdef DEBUG 331 puts ("PHY status read failed\n"); 332 # endif 333 return (-1); 334 } 335 } 336 if ((reg & 0x8000) == 0) { 337 return (0); 338 } else { 339 puts ("PHY reset timed out\n"); 340 return (-1); 341 } 342 return (0); 343 } 344 345 /***************************************************************************** 346 * 347 * Determine the ethernet speed (10/100). 348 */ 349 int miiphy_speed (char *devname, unsigned char addr) 350 { 351 unsigned short reg; 352 353 #if defined(CONFIG_PHY_GIGE) 354 if (miiphy_read (devname, addr, PHY_1000BTSR, ®)) { 355 printf ("PHY 1000BT Status read failed\n"); 356 } else { 357 if (reg != 0xFFFF) { 358 if ((reg & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) 359 != 0) { 360 return (_1000BASET); 361 } 362 } 363 } 364 #endif /* CONFIG_PHY_GIGE */ 365 366 /* Check Basic Management Control Register first. */ 367 if (miiphy_read (devname, addr, PHY_BMCR, ®)) { 368 puts ("PHY speed read failed, assuming 10bT\n"); 369 return (_10BASET); 370 } 371 /* Check if auto-negotiation is on. */ 372 if ((reg & PHY_BMCR_AUTON) != 0) { 373 /* Get auto-negotiation results. */ 374 if (miiphy_read (devname, addr, PHY_ANLPAR, ®)) { 375 puts ("PHY AN speed read failed, assuming 10bT\n"); 376 return (_10BASET); 377 } 378 if ((reg & PHY_ANLPAR_100) != 0) { 379 return (_100BASET); 380 } else { 381 return (_10BASET); 382 } 383 } 384 /* Get speed from basic control settings. */ 385 else if (reg & PHY_BMCR_100MB) { 386 return (_100BASET); 387 } else { 388 return (_10BASET); 389 } 390 391 } 392 393 /***************************************************************************** 394 * 395 * Determine full/half duplex. 396 */ 397 int miiphy_duplex (char *devname, unsigned char addr) 398 { 399 unsigned short reg; 400 401 #if defined(CONFIG_PHY_GIGE) 402 if (miiphy_read (devname, addr, PHY_1000BTSR, ®)) { 403 printf ("PHY 1000BT Status read failed\n"); 404 } else { 405 if ((reg != 0xFFFF) && 406 (reg & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD))) { 407 if ((reg & PHY_1000BTSR_1000FD) != 0) { 408 return (FULL); 409 } else { 410 return (HALF); 411 } 412 } 413 } 414 #endif /* CONFIG_PHY_GIGE */ 415 416 /* Check Basic Management Control Register first. */ 417 if (miiphy_read (devname, addr, PHY_BMCR, ®)) { 418 puts ("PHY duplex read failed, assuming half duplex\n"); 419 return (HALF); 420 } 421 /* Check if auto-negotiation is on. */ 422 if ((reg & PHY_BMCR_AUTON) != 0) { 423 /* Get auto-negotiation results. */ 424 if (miiphy_read (devname, addr, PHY_ANLPAR, ®)) { 425 puts ("PHY AN duplex read failed, assuming half duplex\n"); 426 return (HALF); 427 } 428 429 if ((reg & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) != 0) { 430 return (FULL); 431 } else { 432 return (HALF); 433 } 434 } 435 /* Get speed from basic control settings. */ 436 else if (reg & PHY_BMCR_DPLX) { 437 return (FULL); 438 } else { 439 return (HALF); 440 } 441 442 } 443 444 #ifdef CFG_FAULT_ECHO_LINK_DOWN 445 /***************************************************************************** 446 * 447 * Determine link status 448 */ 449 int miiphy_link (char *devname, unsigned char addr) 450 { 451 unsigned short reg; 452 453 /* dummy read; needed to latch some phys */ 454 (void)miiphy_read (devname, addr, PHY_BMSR, ®); 455 if (miiphy_read (devname, addr, PHY_BMSR, ®)) { 456 puts ("PHY_BMSR read failed, assuming no link\n"); 457 return (0); 458 } 459 460 /* Determine if a link is active */ 461 if ((reg & PHY_BMSR_LS) != 0) { 462 return (1); 463 } else { 464 return (0); 465 } 466 } 467 #endif 468 #endif /* CONFIG_MII */ 469