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) || (CONFIG_COMMANDS & CFG_CMD_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 '%s'\n", 91 name); 92 return; 93 } 94 } 95 96 /* allocate memory */ 97 name_len = strlen(name); 98 new_dev = (struct mii_dev *)malloc(sizeof(struct mii_dev) + name_len + 1); 99 100 if(new_dev == NULL) { 101 printf("miiphy_register: cannot allocate memory for '%s'\n", 102 name); 103 return; 104 } 105 memset(new_dev, 0, sizeof(struct mii_dev) + name_len); 106 107 /* initalize mii_dev struct fields */ 108 INIT_LIST_HEAD(&new_dev->link); 109 new_dev->read = read; 110 new_dev->write = write; 111 new_dev->name = (char *)(new_dev + 1); 112 strncpy(new_dev->name, name, name_len); 113 new_dev->name[name_len] = '\0'; 114 115 debug("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n", 116 new_dev->name, new_dev->read, new_dev->write); 117 118 /* add it to the list */ 119 list_add_tail(&new_dev->link, &mii_devs); 120 121 if (!current_mii) 122 current_mii = new_dev; 123 } 124 125 int miiphy_set_current_dev(char *devname) 126 { 127 struct list_head *entry; 128 struct mii_dev *dev; 129 130 list_for_each(entry, &mii_devs) { 131 dev = list_entry(entry, struct mii_dev, link); 132 133 if (strcmp(devname, dev->name) == 0) { 134 current_mii = dev; 135 return 0; 136 } 137 } 138 139 printf("No such device: %s\n", devname); 140 return 1; 141 } 142 143 char *miiphy_get_current_dev() 144 { 145 if (current_mii) 146 return current_mii->name; 147 148 return NULL; 149 } 150 151 /***************************************************************************** 152 * 153 * Read to variable <value> from the PHY attached to device <devname>, 154 * use PHY address <addr> and register <reg>. 155 * 156 * Returns: 157 * 0 on success 158 */ 159 int miiphy_read(char *devname, unsigned char addr, unsigned char reg, 160 unsigned short *value) 161 { 162 struct list_head *entry; 163 struct mii_dev *dev; 164 int found_dev = 0; 165 int read_ret = 0; 166 167 if (!devname) { 168 printf("NULL device name!\n"); 169 return 1; 170 } 171 172 list_for_each(entry, &mii_devs) { 173 dev = list_entry(entry, struct mii_dev, link); 174 175 if (strcmp(devname, dev->name) == 0) { 176 found_dev = 1; 177 read_ret = dev->read(devname, addr, reg, value); 178 break; 179 } 180 } 181 182 if (found_dev == 0) 183 printf("No such device: %s\n", devname); 184 185 return ((found_dev) ? read_ret : 1); 186 } 187 188 /***************************************************************************** 189 * 190 * Write <value> to the PHY attached to device <devname>, 191 * use PHY address <addr> and register <reg>. 192 * 193 * Returns: 194 * 0 on success 195 */ 196 int miiphy_write(char *devname, unsigned char addr, unsigned char reg, 197 unsigned short value) 198 { 199 struct list_head *entry; 200 struct mii_dev *dev; 201 int found_dev = 0; 202 int write_ret = 0; 203 204 if (!devname) { 205 printf("NULL device name!\n"); 206 return 1; 207 } 208 209 list_for_each(entry, &mii_devs) { 210 dev = list_entry(entry, struct mii_dev, link); 211 212 if (strcmp(devname, dev->name) == 0) { 213 found_dev = 1; 214 write_ret = dev->write(devname, addr, reg, value); 215 break; 216 } 217 } 218 219 if (found_dev == 0) 220 printf("No such device: %s\n", devname); 221 222 return ((found_dev) ? write_ret : 1); 223 } 224 225 /***************************************************************************** 226 * 227 * Print out list of registered MII capable devices. 228 */ 229 void miiphy_listdev(void) 230 { 231 struct list_head *entry; 232 struct mii_dev *dev; 233 234 puts("MII devices: "); 235 list_for_each(entry, &mii_devs) { 236 dev = list_entry(entry, struct mii_dev, link); 237 printf("'%s' ", dev->name); 238 } 239 puts("\n"); 240 241 if (current_mii) 242 printf("Current device: '%s'\n", current_mii->name); 243 } 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, 258 unsigned char addr, 259 unsigned int *oui, 260 unsigned char *model, unsigned char *rev) 261 { 262 unsigned int reg = 0; 263 unsigned short tmp; 264 265 if (miiphy_read (devname, addr, PHY_PHYIDR2, &tmp) != 0) { 266 #ifdef DEBUG 267 puts ("PHY ID register 2 read failed\n"); 268 #endif 269 return (-1); 270 } 271 reg = tmp; 272 273 #ifdef DEBUG 274 printf ("PHY_PHYIDR2 @ 0x%x = 0x%04x\n", addr, reg); 275 #endif 276 if (reg == 0xFFFF) { 277 /* No physical device present at this address */ 278 return (-1); 279 } 280 281 if (miiphy_read (devname, addr, PHY_PHYIDR1, &tmp) != 0) { 282 #ifdef DEBUG 283 puts ("PHY ID register 1 read failed\n"); 284 #endif 285 return (-1); 286 } 287 reg |= tmp << 16; 288 #ifdef DEBUG 289 printf ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg); 290 #endif 291 *oui = ( reg >> 10); 292 *model = (unsigned char) ((reg >> 4) & 0x0000003F); 293 *rev = (unsigned char) ( reg & 0x0000000F); 294 return (0); 295 } 296 297 298 /***************************************************************************** 299 * 300 * Reset the PHY. 301 * Returns: 302 * 0 on success 303 */ 304 int miiphy_reset (char *devname, unsigned char addr) 305 { 306 unsigned short reg; 307 int loop_cnt; 308 309 if (miiphy_read (devname, addr, PHY_BMCR, ®) != 0) { 310 #ifdef DEBUG 311 printf ("PHY status read failed\n"); 312 #endif 313 return (-1); 314 } 315 if (miiphy_write (devname, addr, PHY_BMCR, reg | 0x8000) != 0) { 316 #ifdef DEBUG 317 puts ("PHY reset failed\n"); 318 #endif 319 return (-1); 320 } 321 #ifdef CONFIG_PHY_RESET_DELAY 322 udelay (CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */ 323 #endif 324 /* 325 * Poll the control register for the reset bit to go to 0 (it is 326 * auto-clearing). This should happen within 0.5 seconds per the 327 * IEEE spec. 328 */ 329 loop_cnt = 0; 330 reg = 0x8000; 331 while (((reg & 0x8000) != 0) && (loop_cnt++ < 1000000)) { 332 if (miiphy_read (devname, addr, PHY_BMCR, ®) != 0) { 333 # ifdef DEBUG 334 puts ("PHY status read failed\n"); 335 # endif 336 return (-1); 337 } 338 } 339 if ((reg & 0x8000) == 0) { 340 return (0); 341 } else { 342 puts ("PHY reset timed out\n"); 343 return (-1); 344 } 345 return (0); 346 } 347 348 349 /***************************************************************************** 350 * 351 * Determine the ethernet speed (10/100). 352 */ 353 int miiphy_speed (char *devname, unsigned char addr) 354 { 355 unsigned short reg; 356 357 #if defined(CONFIG_PHY_GIGE) 358 if (miiphy_read (devname, addr, PHY_1000BTSR, ®)) { 359 printf ("PHY 1000BT Status read failed\n"); 360 } else { 361 if (reg != 0xFFFF) { 362 if ((reg & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) !=0) { 363 return (_1000BASET); 364 } 365 } 366 } 367 #endif /* CONFIG_PHY_GIGE */ 368 369 /* Check Basic Management Control Register first. */ 370 if (miiphy_read (devname, addr, PHY_BMCR, ®)) { 371 puts ("PHY speed read failed, assuming 10bT\n"); 372 return (_10BASET); 373 } 374 /* Check if auto-negotiation is on. */ 375 if ((reg & PHY_BMCR_AUTON) != 0) { 376 /* Get auto-negotiation results. */ 377 if (miiphy_read (devname, addr, PHY_ANLPAR, ®)) { 378 puts ("PHY AN speed read failed, assuming 10bT\n"); 379 return (_10BASET); 380 } 381 if ((reg & PHY_ANLPAR_100) != 0) { 382 return (_100BASET); 383 } else { 384 return (_10BASET); 385 } 386 } 387 /* Get speed from basic control settings. */ 388 else if (reg & PHY_BMCR_100MB) { 389 return (_100BASET); 390 } else { 391 return (_10BASET); 392 } 393 394 } 395 396 397 /***************************************************************************** 398 * 399 * Determine full/half duplex. 400 */ 401 int miiphy_duplex (char *devname, unsigned char addr) 402 { 403 unsigned short reg; 404 405 #if defined(CONFIG_PHY_GIGE) 406 if (miiphy_read (devname, addr, PHY_1000BTSR, ®)) { 407 printf ("PHY 1000BT Status read failed\n"); 408 } else { 409 if ( (reg != 0xFFFF) && 410 (reg & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) ) { 411 if ((reg & PHY_1000BTSR_1000FD) !=0) { 412 return (FULL); 413 } else { 414 return (HALF); 415 } 416 } 417 } 418 #endif /* CONFIG_PHY_GIGE */ 419 420 /* Check Basic Management Control Register first. */ 421 if (miiphy_read (devname, addr, PHY_BMCR, ®)) { 422 puts ("PHY duplex read failed, assuming half duplex\n"); 423 return (HALF); 424 } 425 /* Check if auto-negotiation is on. */ 426 if ((reg & PHY_BMCR_AUTON) != 0) { 427 /* Get auto-negotiation results. */ 428 if (miiphy_read (devname, addr, PHY_ANLPAR, ®)) { 429 puts ("PHY AN duplex read failed, assuming half duplex\n"); 430 return (HALF); 431 } 432 433 if ((reg & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) != 0) { 434 return (FULL); 435 } else { 436 return (HALF); 437 } 438 } 439 /* Get speed from basic control settings. */ 440 else if (reg & PHY_BMCR_DPLX) { 441 return (FULL); 442 } else { 443 return (HALF); 444 } 445 446 } 447 448 #ifdef CFG_FAULT_ECHO_LINK_DOWN 449 /***************************************************************************** 450 * 451 * Determine link status 452 */ 453 int miiphy_link (char *devname, unsigned char addr) 454 { 455 unsigned short reg; 456 457 /* dummy read; needed to latch some phys */ 458 (void)miiphy_read(devname, addr, PHY_BMSR, ®); 459 if (miiphy_read (devname, addr, PHY_BMSR, ®)) { 460 puts ("PHY_BMSR read failed, assuming no link\n"); 461 return (0); 462 } 463 464 /* Determine if a link is active */ 465 if ((reg & PHY_BMSR_LS) != 0) { 466 return (1); 467 } else { 468 return (0); 469 } 470 } 471 #endif 472 473 #endif /* CONFIG_MII || (CONFIG_COMMANDS & CFG_CMD_MII) */ 474