1 /* 2 * Freescale Three Speed Ethernet Controller driver 3 * 4 * This software may be used and distributed according to the 5 * terms of the GNU Public License, Version 2, incorporated 6 * herein by reference. 7 * 8 * Copyright 2004-2009 Freescale Semiconductor, Inc. 9 * (C) Copyright 2003, Motorola, Inc. 10 * author Andy Fleming 11 * 12 */ 13 14 #include <config.h> 15 #include <common.h> 16 #include <malloc.h> 17 #include <net.h> 18 #include <command.h> 19 #include <tsec.h> 20 #include <asm/errno.h> 21 22 #include "miiphy.h" 23 24 DECLARE_GLOBAL_DATA_PTR; 25 26 #define TX_BUF_CNT 2 27 28 static uint rxIdx; /* index of the current RX buffer */ 29 static uint txIdx; /* index of the current TX buffer */ 30 31 typedef volatile struct rtxbd { 32 txbd8_t txbd[TX_BUF_CNT]; 33 rxbd8_t rxbd[PKTBUFSRX]; 34 } RTXBD; 35 36 #define MAXCONTROLLERS (8) 37 38 static struct tsec_private *privlist[MAXCONTROLLERS]; 39 static int num_tsecs = 0; 40 41 #ifdef __GNUC__ 42 static RTXBD rtx __attribute__ ((aligned(8))); 43 #else 44 #error "rtx must be 64-bit aligned" 45 #endif 46 47 static int tsec_send(struct eth_device *dev, 48 volatile void *packet, int length); 49 static int tsec_recv(struct eth_device *dev); 50 static int tsec_init(struct eth_device *dev, bd_t * bd); 51 static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info); 52 static void tsec_halt(struct eth_device *dev); 53 static void init_registers(volatile tsec_t * regs); 54 static void startup_tsec(struct eth_device *dev); 55 static int init_phy(struct eth_device *dev); 56 void write_phy_reg(struct tsec_private *priv, uint regnum, uint value); 57 uint read_phy_reg(struct tsec_private *priv, uint regnum); 58 static struct phy_info *get_phy_info(struct eth_device *dev); 59 static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd); 60 static void adjust_link(struct eth_device *dev); 61 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ 62 && !defined(BITBANGMII) 63 static int tsec_miiphy_write(char *devname, unsigned char addr, 64 unsigned char reg, unsigned short value); 65 static int tsec_miiphy_read(char *devname, unsigned char addr, 66 unsigned char reg, unsigned short *value); 67 #endif 68 #ifdef CONFIG_MCAST_TFTP 69 static int tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set); 70 #endif 71 72 /* Default initializations for TSEC controllers. */ 73 74 static struct tsec_info_struct tsec_info[] = { 75 #ifdef CONFIG_TSEC1 76 STD_TSEC_INFO(1), /* TSEC1 */ 77 #endif 78 #ifdef CONFIG_TSEC2 79 STD_TSEC_INFO(2), /* TSEC2 */ 80 #endif 81 #ifdef CONFIG_MPC85XX_FEC 82 { 83 .regs = (tsec_t *)(TSEC_BASE_ADDR + 0x2000), 84 .miiregs = (tsec_mdio_t *)(MDIO_BASE_ADDR), 85 .devname = CONFIG_MPC85XX_FEC_NAME, 86 .phyaddr = FEC_PHY_ADDR, 87 .flags = FEC_FLAGS 88 }, /* FEC */ 89 #endif 90 #ifdef CONFIG_TSEC3 91 STD_TSEC_INFO(3), /* TSEC3 */ 92 #endif 93 #ifdef CONFIG_TSEC4 94 STD_TSEC_INFO(4), /* TSEC4 */ 95 #endif 96 }; 97 98 int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num) 99 { 100 int i; 101 102 for (i = 0; i < num; i++) 103 tsec_initialize(bis, &tsecs[i]); 104 105 return 0; 106 } 107 108 int tsec_standard_init(bd_t *bis) 109 { 110 return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info)); 111 } 112 113 /* Initialize device structure. Returns success if PHY 114 * initialization succeeded (i.e. if it recognizes the PHY) 115 */ 116 static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info) 117 { 118 struct eth_device *dev; 119 int i; 120 struct tsec_private *priv; 121 122 dev = (struct eth_device *)malloc(sizeof *dev); 123 124 if (NULL == dev) 125 return 0; 126 127 memset(dev, 0, sizeof *dev); 128 129 priv = (struct tsec_private *)malloc(sizeof(*priv)); 130 131 if (NULL == priv) 132 return 0; 133 134 privlist[num_tsecs++] = priv; 135 priv->regs = tsec_info->regs; 136 priv->phyregs = tsec_info->miiregs; 137 priv->phyregs_sgmii = tsec_info->miiregs_sgmii; 138 139 priv->phyaddr = tsec_info->phyaddr; 140 priv->flags = tsec_info->flags; 141 142 sprintf(dev->name, tsec_info->devname); 143 dev->iobase = 0; 144 dev->priv = priv; 145 dev->init = tsec_init; 146 dev->halt = tsec_halt; 147 dev->send = tsec_send; 148 dev->recv = tsec_recv; 149 #ifdef CONFIG_MCAST_TFTP 150 dev->mcast = tsec_mcast_addr; 151 #endif 152 153 /* Tell u-boot to get the addr from the env */ 154 for (i = 0; i < 6; i++) 155 dev->enetaddr[i] = 0; 156 157 eth_register(dev); 158 159 /* Reset the MAC */ 160 priv->regs->maccfg1 |= MACCFG1_SOFT_RESET; 161 udelay(2); /* Soft Reset must be asserted for 3 TX clocks */ 162 priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET); 163 164 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ 165 && !defined(BITBANGMII) 166 miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write); 167 #endif 168 169 /* Try to initialize PHY here, and return */ 170 return init_phy(dev); 171 } 172 173 /* Initializes data structures and registers for the controller, 174 * and brings the interface up. Returns the link status, meaning 175 * that it returns success if the link is up, failure otherwise. 176 * This allows u-boot to find the first active controller. 177 */ 178 static int tsec_init(struct eth_device *dev, bd_t * bd) 179 { 180 uint tempval; 181 char tmpbuf[MAC_ADDR_LEN]; 182 int i; 183 struct tsec_private *priv = (struct tsec_private *)dev->priv; 184 volatile tsec_t *regs = priv->regs; 185 186 /* Make sure the controller is stopped */ 187 tsec_halt(dev); 188 189 /* Init MACCFG2. Defaults to GMII */ 190 regs->maccfg2 = MACCFG2_INIT_SETTINGS; 191 192 /* Init ECNTRL */ 193 regs->ecntrl = ECNTRL_INIT_SETTINGS; 194 195 /* Copy the station address into the address registers. 196 * Backwards, because little endian MACS are dumb */ 197 for (i = 0; i < MAC_ADDR_LEN; i++) { 198 tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i]; 199 } 200 tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) | 201 tmpbuf[3]; 202 203 regs->macstnaddr1 = tempval; 204 205 tempval = *((uint *) (tmpbuf + 4)); 206 207 regs->macstnaddr2 = tempval; 208 209 /* reset the indices to zero */ 210 rxIdx = 0; 211 txIdx = 0; 212 213 /* Clear out (for the most part) the other registers */ 214 init_registers(regs); 215 216 /* Ready the device for tx/rx */ 217 startup_tsec(dev); 218 219 /* If there's no link, fail */ 220 return (priv->link ? 0 : -1); 221 } 222 223 /* Writes the given phy's reg with value, using the specified MDIO regs */ 224 static void tsec_local_mdio_write(volatile tsec_mdio_t *phyregs, uint addr, 225 uint reg, uint value) 226 { 227 int timeout = 1000000; 228 229 phyregs->miimadd = (addr << 8) | reg; 230 phyregs->miimcon = value; 231 asm("sync"); 232 233 timeout = 1000000; 234 while ((phyregs->miimind & MIIMIND_BUSY) && timeout--) ; 235 } 236 237 238 /* Provide the default behavior of writing the PHY of this ethernet device */ 239 #define write_phy_reg(priv, regnum, value) tsec_local_mdio_write(priv->phyregs,priv->phyaddr,regnum,value) 240 241 /* Reads register regnum on the device's PHY through the 242 * specified registers. It lowers and raises the read 243 * command, and waits for the data to become valid (miimind 244 * notvalid bit cleared), and the bus to cease activity (miimind 245 * busy bit cleared), and then returns the value 246 */ 247 static uint tsec_local_mdio_read(volatile tsec_mdio_t *phyregs, 248 uint phyid, uint regnum) 249 { 250 uint value; 251 252 /* Put the address of the phy, and the register 253 * number into MIIMADD */ 254 phyregs->miimadd = (phyid << 8) | regnum; 255 256 /* Clear the command register, and wait */ 257 phyregs->miimcom = 0; 258 asm("sync"); 259 260 /* Initiate a read command, and wait */ 261 phyregs->miimcom = MIIM_READ_COMMAND; 262 asm("sync"); 263 264 /* Wait for the the indication that the read is done */ 265 while ((phyregs->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ; 266 267 /* Grab the value read from the PHY */ 268 value = phyregs->miimstat; 269 270 return value; 271 } 272 273 /* #define to provide old read_phy_reg functionality without duplicating code */ 274 #define read_phy_reg(priv,regnum) tsec_local_mdio_read(priv->phyregs,priv->phyaddr,regnum) 275 276 #define TBIANA_SETTINGS ( \ 277 TBIANA_ASYMMETRIC_PAUSE \ 278 | TBIANA_SYMMETRIC_PAUSE \ 279 | TBIANA_FULL_DUPLEX \ 280 ) 281 282 /* Force the TBI PHY into 1000Mbps full duplex when in SGMII mode */ 283 #define TBICR_SETTINGS ( \ 284 TBICR_PHY_RESET \ 285 | TBICR_FULL_DUPLEX \ 286 | TBICR_SPEED1_SET \ 287 ) 288 289 /* Configure the TBI for SGMII operation */ 290 static void tsec_configure_serdes(struct tsec_private *priv) 291 { 292 /* Access TBI PHY registers at given TSEC register offset as opposed to the 293 * register offset used for external PHY accesses */ 294 tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_ANA, 295 TBIANA_SETTINGS); 296 tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_TBICON, 297 TBICON_CLK_SELECT); 298 tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_CR, 299 TBICR_SETTINGS); 300 } 301 302 /* Discover which PHY is attached to the device, and configure it 303 * properly. If the PHY is not recognized, then return 0 304 * (failure). Otherwise, return 1 305 */ 306 static int init_phy(struct eth_device *dev) 307 { 308 struct tsec_private *priv = (struct tsec_private *)dev->priv; 309 struct phy_info *curphy; 310 volatile tsec_t *regs = priv->regs; 311 312 /* Assign a Physical address to the TBI */ 313 regs->tbipa = CONFIG_SYS_TBIPA_VALUE; 314 asm("sync"); 315 316 /* Reset MII (due to new addresses) */ 317 priv->phyregs->miimcfg = MIIMCFG_RESET; 318 asm("sync"); 319 priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE; 320 asm("sync"); 321 while (priv->phyregs->miimind & MIIMIND_BUSY) ; 322 323 /* Get the cmd structure corresponding to the attached 324 * PHY */ 325 curphy = get_phy_info(dev); 326 327 if (curphy == NULL) { 328 priv->phyinfo = NULL; 329 printf("%s: No PHY found\n", dev->name); 330 331 return 0; 332 } 333 334 if (regs->ecntrl & ECNTRL_SGMII_MODE) 335 tsec_configure_serdes(priv); 336 337 priv->phyinfo = curphy; 338 339 phy_run_commands(priv, priv->phyinfo->config); 340 341 return 1; 342 } 343 344 /* 345 * Returns which value to write to the control register. 346 * For 10/100, the value is slightly different 347 */ 348 static uint mii_cr_init(uint mii_reg, struct tsec_private * priv) 349 { 350 if (priv->flags & TSEC_GIGABIT) 351 return MIIM_CONTROL_INIT; 352 else 353 return MIIM_CR_INIT; 354 } 355 356 /* 357 * Wait for auto-negotiation to complete, then determine link 358 */ 359 static uint mii_parse_sr(uint mii_reg, struct tsec_private * priv) 360 { 361 /* 362 * Wait if the link is up, and autonegotiation is in progress 363 * (ie - we're capable and it's not done) 364 */ 365 mii_reg = read_phy_reg(priv, MIIM_STATUS); 366 if ((mii_reg & PHY_BMSR_AUTN_ABLE) && !(mii_reg & PHY_BMSR_AUTN_COMP)) { 367 int i = 0; 368 369 puts("Waiting for PHY auto negotiation to complete"); 370 while (!(mii_reg & PHY_BMSR_AUTN_COMP)) { 371 /* 372 * Timeout reached ? 373 */ 374 if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 375 puts(" TIMEOUT !\n"); 376 priv->link = 0; 377 return 0; 378 } 379 380 if (ctrlc()) { 381 puts("user interrupt!\n"); 382 priv->link = 0; 383 return -EINTR; 384 } 385 386 if ((i++ % 1000) == 0) { 387 putc('.'); 388 } 389 udelay(1000); /* 1 ms */ 390 mii_reg = read_phy_reg(priv, MIIM_STATUS); 391 } 392 puts(" done\n"); 393 394 /* Link status bit is latched low, read it again */ 395 mii_reg = read_phy_reg(priv, MIIM_STATUS); 396 397 udelay(500000); /* another 500 ms (results in faster booting) */ 398 } 399 400 priv->link = mii_reg & MIIM_STATUS_LINK ? 1 : 0; 401 402 return 0; 403 } 404 405 /* Generic function which updates the speed and duplex. If 406 * autonegotiation is enabled, it uses the AND of the link 407 * partner's advertised capabilities and our advertised 408 * capabilities. If autonegotiation is disabled, we use the 409 * appropriate bits in the control register. 410 * 411 * Stolen from Linux's mii.c and phy_device.c 412 */ 413 static uint mii_parse_link(uint mii_reg, struct tsec_private *priv) 414 { 415 /* We're using autonegotiation */ 416 if (mii_reg & PHY_BMSR_AUTN_ABLE) { 417 uint lpa = 0; 418 uint gblpa = 0; 419 420 /* Check for gigabit capability */ 421 if (mii_reg & PHY_BMSR_EXT) { 422 /* We want a list of states supported by 423 * both PHYs in the link 424 */ 425 gblpa = read_phy_reg(priv, PHY_1000BTSR); 426 gblpa &= read_phy_reg(priv, PHY_1000BTCR) << 2; 427 } 428 429 /* Set the baseline so we only have to set them 430 * if they're different 431 */ 432 priv->speed = 10; 433 priv->duplexity = 0; 434 435 /* Check the gigabit fields */ 436 if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) { 437 priv->speed = 1000; 438 439 if (gblpa & PHY_1000BTSR_1000FD) 440 priv->duplexity = 1; 441 442 /* We're done! */ 443 return 0; 444 } 445 446 lpa = read_phy_reg(priv, PHY_ANAR); 447 lpa &= read_phy_reg(priv, PHY_ANLPAR); 448 449 if (lpa & (PHY_ANLPAR_TXFD | PHY_ANLPAR_TX)) { 450 priv->speed = 100; 451 452 if (lpa & PHY_ANLPAR_TXFD) 453 priv->duplexity = 1; 454 455 } else if (lpa & PHY_ANLPAR_10FD) 456 priv->duplexity = 1; 457 } else { 458 uint bmcr = read_phy_reg(priv, PHY_BMCR); 459 460 priv->speed = 10; 461 priv->duplexity = 0; 462 463 if (bmcr & PHY_BMCR_DPLX) 464 priv->duplexity = 1; 465 466 if (bmcr & PHY_BMCR_1000_MBPS) 467 priv->speed = 1000; 468 else if (bmcr & PHY_BMCR_100_MBPS) 469 priv->speed = 100; 470 } 471 472 return 0; 473 } 474 475 /* 476 * "Ethernet@Wirespeed" needs to be enabled to achieve link in certain 477 * circumstances. eg a gigabit TSEC connected to a gigabit switch with 478 * a 4-wire ethernet cable. Both ends advertise gigabit, but can't 479 * link. "Ethernet@Wirespeed" reduces advertised speed until link 480 * can be achieved. 481 */ 482 static uint mii_BCM54xx_wirespeed(uint mii_reg, struct tsec_private *priv) 483 { 484 return (read_phy_reg(priv, mii_reg) & 0x8FFF) | 0x8010; 485 } 486 487 /* 488 * Parse the BCM54xx status register for speed and duplex information. 489 * The linux sungem_phy has this information, but in a table format. 490 */ 491 static uint mii_parse_BCM54xx_sr(uint mii_reg, struct tsec_private *priv) 492 { 493 /* If there is no link, speed and duplex don't matter */ 494 if (!priv->link) 495 return 0; 496 497 switch ((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >> 498 MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT) { 499 case 1: 500 priv->duplexity = 0; 501 priv->speed = 10; 502 break; 503 case 2: 504 priv->duplexity = 1; 505 priv->speed = 10; 506 break; 507 case 3: 508 priv->duplexity = 0; 509 priv->speed = 100; 510 break; 511 case 5: 512 priv->duplexity = 1; 513 priv->speed = 100; 514 break; 515 case 6: 516 priv->duplexity = 0; 517 priv->speed = 1000; 518 break; 519 case 7: 520 priv->duplexity = 1; 521 priv->speed = 1000; 522 break; 523 default: 524 printf("Auto-neg error, defaulting to 10BT/HD\n"); 525 priv->duplexity = 0; 526 priv->speed = 10; 527 break; 528 } 529 530 return 0; 531 532 } 533 /* Parse the 88E1011's status register for speed and duplex 534 * information 535 */ 536 static uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv) 537 { 538 uint speed; 539 540 mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS); 541 542 if ((mii_reg & MIIM_88E1011_PHYSTAT_LINK) && 543 !(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) { 544 int i = 0; 545 546 puts("Waiting for PHY realtime link"); 547 while (!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) { 548 /* Timeout reached ? */ 549 if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 550 puts(" TIMEOUT !\n"); 551 priv->link = 0; 552 break; 553 } 554 555 if ((i++ % 1000) == 0) { 556 putc('.'); 557 } 558 udelay(1000); /* 1 ms */ 559 mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS); 560 } 561 puts(" done\n"); 562 udelay(500000); /* another 500 ms (results in faster booting) */ 563 } else { 564 if (mii_reg & MIIM_88E1011_PHYSTAT_LINK) 565 priv->link = 1; 566 else 567 priv->link = 0; 568 } 569 570 if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX) 571 priv->duplexity = 1; 572 else 573 priv->duplexity = 0; 574 575 speed = (mii_reg & MIIM_88E1011_PHYSTAT_SPEED); 576 577 switch (speed) { 578 case MIIM_88E1011_PHYSTAT_GBIT: 579 priv->speed = 1000; 580 break; 581 case MIIM_88E1011_PHYSTAT_100: 582 priv->speed = 100; 583 break; 584 default: 585 priv->speed = 10; 586 } 587 588 return 0; 589 } 590 591 /* Parse the RTL8211B's status register for speed and duplex 592 * information 593 */ 594 static uint mii_parse_RTL8211B_sr(uint mii_reg, struct tsec_private * priv) 595 { 596 uint speed; 597 598 mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS); 599 if (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) { 600 int i = 0; 601 602 /* in case of timeout ->link is cleared */ 603 priv->link = 1; 604 puts("Waiting for PHY realtime link"); 605 while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) { 606 /* Timeout reached ? */ 607 if (i > PHY_AUTONEGOTIATE_TIMEOUT) { 608 puts(" TIMEOUT !\n"); 609 priv->link = 0; 610 break; 611 } 612 613 if ((i++ % 1000) == 0) { 614 putc('.'); 615 } 616 udelay(1000); /* 1 ms */ 617 mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS); 618 } 619 puts(" done\n"); 620 udelay(500000); /* another 500 ms (results in faster booting) */ 621 } else { 622 if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK) 623 priv->link = 1; 624 else 625 priv->link = 0; 626 } 627 628 if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX) 629 priv->duplexity = 1; 630 else 631 priv->duplexity = 0; 632 633 speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED); 634 635 switch (speed) { 636 case MIIM_RTL8211B_PHYSTAT_GBIT: 637 priv->speed = 1000; 638 break; 639 case MIIM_RTL8211B_PHYSTAT_100: 640 priv->speed = 100; 641 break; 642 default: 643 priv->speed = 10; 644 } 645 646 return 0; 647 } 648 649 /* Parse the cis8201's status register for speed and duplex 650 * information 651 */ 652 static uint mii_parse_cis8201(uint mii_reg, struct tsec_private * priv) 653 { 654 uint speed; 655 656 if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX) 657 priv->duplexity = 1; 658 else 659 priv->duplexity = 0; 660 661 speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED; 662 switch (speed) { 663 case MIIM_CIS8201_AUXCONSTAT_GBIT: 664 priv->speed = 1000; 665 break; 666 case MIIM_CIS8201_AUXCONSTAT_100: 667 priv->speed = 100; 668 break; 669 default: 670 priv->speed = 10; 671 break; 672 } 673 674 return 0; 675 } 676 677 /* Parse the vsc8244's status register for speed and duplex 678 * information 679 */ 680 static uint mii_parse_vsc8244(uint mii_reg, struct tsec_private * priv) 681 { 682 uint speed; 683 684 if (mii_reg & MIIM_VSC8244_AUXCONSTAT_DUPLEX) 685 priv->duplexity = 1; 686 else 687 priv->duplexity = 0; 688 689 speed = mii_reg & MIIM_VSC8244_AUXCONSTAT_SPEED; 690 switch (speed) { 691 case MIIM_VSC8244_AUXCONSTAT_GBIT: 692 priv->speed = 1000; 693 break; 694 case MIIM_VSC8244_AUXCONSTAT_100: 695 priv->speed = 100; 696 break; 697 default: 698 priv->speed = 10; 699 break; 700 } 701 702 return 0; 703 } 704 705 /* Parse the DM9161's status register for speed and duplex 706 * information 707 */ 708 static uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private * priv) 709 { 710 if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H)) 711 priv->speed = 100; 712 else 713 priv->speed = 10; 714 715 if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F)) 716 priv->duplexity = 1; 717 else 718 priv->duplexity = 0; 719 720 return 0; 721 } 722 723 /* 724 * Hack to write all 4 PHYs with the LED values 725 */ 726 static uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv) 727 { 728 uint phyid; 729 volatile tsec_mdio_t *regbase = priv->phyregs; 730 int timeout = 1000000; 731 732 for (phyid = 0; phyid < 4; phyid++) { 733 regbase->miimadd = (phyid << 8) | mii_reg; 734 regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT; 735 asm("sync"); 736 737 timeout = 1000000; 738 while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ; 739 } 740 741 return MIIM_CIS8204_SLEDCON_INIT; 742 } 743 744 static uint mii_cis8204_setmode(uint mii_reg, struct tsec_private * priv) 745 { 746 if (priv->flags & TSEC_REDUCED) 747 return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII; 748 else 749 return MIIM_CIS8204_EPHYCON_INIT; 750 } 751 752 static uint mii_m88e1111s_setmode(uint mii_reg, struct tsec_private *priv) 753 { 754 uint mii_data = read_phy_reg(priv, mii_reg); 755 756 if (priv->flags & TSEC_REDUCED) 757 mii_data = (mii_data & 0xfff0) | 0x000b; 758 return mii_data; 759 } 760 761 /* Initialized required registers to appropriate values, zeroing 762 * those we don't care about (unless zero is bad, in which case, 763 * choose a more appropriate value) 764 */ 765 static void init_registers(volatile tsec_t * regs) 766 { 767 /* Clear IEVENT */ 768 regs->ievent = IEVENT_INIT_CLEAR; 769 770 regs->imask = IMASK_INIT_CLEAR; 771 772 regs->hash.iaddr0 = 0; 773 regs->hash.iaddr1 = 0; 774 regs->hash.iaddr2 = 0; 775 regs->hash.iaddr3 = 0; 776 regs->hash.iaddr4 = 0; 777 regs->hash.iaddr5 = 0; 778 regs->hash.iaddr6 = 0; 779 regs->hash.iaddr7 = 0; 780 781 regs->hash.gaddr0 = 0; 782 regs->hash.gaddr1 = 0; 783 regs->hash.gaddr2 = 0; 784 regs->hash.gaddr3 = 0; 785 regs->hash.gaddr4 = 0; 786 regs->hash.gaddr5 = 0; 787 regs->hash.gaddr6 = 0; 788 regs->hash.gaddr7 = 0; 789 790 regs->rctrl = 0x00000000; 791 792 /* Init RMON mib registers */ 793 memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t)); 794 795 regs->rmon.cam1 = 0xffffffff; 796 regs->rmon.cam2 = 0xffffffff; 797 798 regs->mrblr = MRBLR_INIT_SETTINGS; 799 800 regs->minflr = MINFLR_INIT_SETTINGS; 801 802 regs->attr = ATTR_INIT_SETTINGS; 803 regs->attreli = ATTRELI_INIT_SETTINGS; 804 805 } 806 807 /* Configure maccfg2 based on negotiated speed and duplex 808 * reported by PHY handling code 809 */ 810 static void adjust_link(struct eth_device *dev) 811 { 812 struct tsec_private *priv = (struct tsec_private *)dev->priv; 813 volatile tsec_t *regs = priv->regs; 814 815 if (priv->link) { 816 if (priv->duplexity != 0) 817 regs->maccfg2 |= MACCFG2_FULL_DUPLEX; 818 else 819 regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX); 820 821 switch (priv->speed) { 822 case 1000: 823 regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF)) 824 | MACCFG2_GMII); 825 break; 826 case 100: 827 case 10: 828 regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF)) 829 | MACCFG2_MII); 830 831 /* Set R100 bit in all modes although 832 * it is only used in RGMII mode 833 */ 834 if (priv->speed == 100) 835 regs->ecntrl |= ECNTRL_R100; 836 else 837 regs->ecntrl &= ~(ECNTRL_R100); 838 break; 839 default: 840 printf("%s: Speed was bad\n", dev->name); 841 break; 842 } 843 844 printf("Speed: %d, %s duplex\n", priv->speed, 845 (priv->duplexity) ? "full" : "half"); 846 847 } else { 848 printf("%s: No link.\n", dev->name); 849 } 850 } 851 852 /* Set up the buffers and their descriptors, and bring up the 853 * interface 854 */ 855 static void startup_tsec(struct eth_device *dev) 856 { 857 int i; 858 struct tsec_private *priv = (struct tsec_private *)dev->priv; 859 volatile tsec_t *regs = priv->regs; 860 861 /* Point to the buffer descriptors */ 862 regs->tbase = (unsigned int)(&rtx.txbd[txIdx]); 863 regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]); 864 865 /* Initialize the Rx Buffer descriptors */ 866 for (i = 0; i < PKTBUFSRX; i++) { 867 rtx.rxbd[i].status = RXBD_EMPTY; 868 rtx.rxbd[i].length = 0; 869 rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i]; 870 } 871 rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP; 872 873 /* Initialize the TX Buffer Descriptors */ 874 for (i = 0; i < TX_BUF_CNT; i++) { 875 rtx.txbd[i].status = 0; 876 rtx.txbd[i].length = 0; 877 rtx.txbd[i].bufPtr = 0; 878 } 879 rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP; 880 881 /* Start up the PHY */ 882 if(priv->phyinfo) 883 phy_run_commands(priv, priv->phyinfo->startup); 884 885 adjust_link(dev); 886 887 /* Enable Transmit and Receive */ 888 regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN); 889 890 /* Tell the DMA it is clear to go */ 891 regs->dmactrl |= DMACTRL_INIT_SETTINGS; 892 regs->tstat = TSTAT_CLEAR_THALT; 893 regs->rstat = RSTAT_CLEAR_RHALT; 894 regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS); 895 } 896 897 /* This returns the status bits of the device. The return value 898 * is never checked, and this is what the 8260 driver did, so we 899 * do the same. Presumably, this would be zero if there were no 900 * errors 901 */ 902 static int tsec_send(struct eth_device *dev, volatile void *packet, int length) 903 { 904 int i; 905 int result = 0; 906 struct tsec_private *priv = (struct tsec_private *)dev->priv; 907 volatile tsec_t *regs = priv->regs; 908 909 /* Find an empty buffer descriptor */ 910 for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { 911 if (i >= TOUT_LOOP) { 912 debug("%s: tsec: tx buffers full\n", dev->name); 913 return result; 914 } 915 } 916 917 rtx.txbd[txIdx].bufPtr = (uint) packet; 918 rtx.txbd[txIdx].length = length; 919 rtx.txbd[txIdx].status |= 920 (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT); 921 922 /* Tell the DMA to go */ 923 regs->tstat = TSTAT_CLEAR_THALT; 924 925 /* Wait for buffer to be transmitted */ 926 for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { 927 if (i >= TOUT_LOOP) { 928 debug("%s: tsec: tx error\n", dev->name); 929 return result; 930 } 931 } 932 933 txIdx = (txIdx + 1) % TX_BUF_CNT; 934 result = rtx.txbd[txIdx].status & TXBD_STATS; 935 936 return result; 937 } 938 939 static int tsec_recv(struct eth_device *dev) 940 { 941 int length; 942 struct tsec_private *priv = (struct tsec_private *)dev->priv; 943 volatile tsec_t *regs = priv->regs; 944 945 while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) { 946 947 length = rtx.rxbd[rxIdx].length; 948 949 /* Send the packet up if there were no errors */ 950 if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) { 951 NetReceive(NetRxPackets[rxIdx], length - 4); 952 } else { 953 printf("Got error %x\n", 954 (rtx.rxbd[rxIdx].status & RXBD_STATS)); 955 } 956 957 rtx.rxbd[rxIdx].length = 0; 958 959 /* Set the wrap bit if this is the last element in the list */ 960 rtx.rxbd[rxIdx].status = 961 RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0); 962 963 rxIdx = (rxIdx + 1) % PKTBUFSRX; 964 } 965 966 if (regs->ievent & IEVENT_BSY) { 967 regs->ievent = IEVENT_BSY; 968 regs->rstat = RSTAT_CLEAR_RHALT; 969 } 970 971 return -1; 972 973 } 974 975 /* Stop the interface */ 976 static void tsec_halt(struct eth_device *dev) 977 { 978 struct tsec_private *priv = (struct tsec_private *)dev->priv; 979 volatile tsec_t *regs = priv->regs; 980 981 regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS); 982 regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS); 983 984 while (!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC))) ; 985 986 regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN); 987 988 /* Shut down the PHY, as needed */ 989 if(priv->phyinfo) 990 phy_run_commands(priv, priv->phyinfo->shutdown); 991 } 992 993 static struct phy_info phy_info_M88E1149S = { 994 0x1410ca, 995 "Marvell 88E1149S", 996 4, 997 (struct phy_cmd[]){ /* config */ 998 /* Reset and configure the PHY */ 999 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1000 {0x1d, 0x1f, NULL}, 1001 {0x1e, 0x200c, NULL}, 1002 {0x1d, 0x5, NULL}, 1003 {0x1e, 0x0, NULL}, 1004 {0x1e, 0x100, NULL}, 1005 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, 1006 {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, 1007 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1008 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1009 {miim_end,} 1010 }, 1011 (struct phy_cmd[]){ /* startup */ 1012 /* Status is read once to clear old link state */ 1013 {MIIM_STATUS, miim_read, NULL}, 1014 /* Auto-negotiate */ 1015 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1016 /* Read the status */ 1017 {MIIM_88E1011_PHY_STATUS, miim_read, 1018 &mii_parse_88E1011_psr}, 1019 {miim_end,} 1020 }, 1021 (struct phy_cmd[]){ /* shutdown */ 1022 {miim_end,} 1023 }, 1024 }; 1025 1026 /* The 5411 id is 0x206070, the 5421 is 0x2060e0 */ 1027 static struct phy_info phy_info_BCM5461S = { 1028 0x02060c1, /* 5461 ID */ 1029 "Broadcom BCM5461S", 1030 0, /* not clear to me what minor revisions we can shift away */ 1031 (struct phy_cmd[]) { /* config */ 1032 /* Reset and configure the PHY */ 1033 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1034 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, 1035 {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, 1036 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1037 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1038 {miim_end,} 1039 }, 1040 (struct phy_cmd[]) { /* startup */ 1041 /* Status is read once to clear old link state */ 1042 {MIIM_STATUS, miim_read, NULL}, 1043 /* Auto-negotiate */ 1044 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1045 /* Read the status */ 1046 {MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr}, 1047 {miim_end,} 1048 }, 1049 (struct phy_cmd[]) { /* shutdown */ 1050 {miim_end,} 1051 }, 1052 }; 1053 1054 static struct phy_info phy_info_BCM5464S = { 1055 0x02060b1, /* 5464 ID */ 1056 "Broadcom BCM5464S", 1057 0, /* not clear to me what minor revisions we can shift away */ 1058 (struct phy_cmd[]) { /* config */ 1059 /* Reset and configure the PHY */ 1060 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1061 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, 1062 {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, 1063 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1064 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1065 {miim_end,} 1066 }, 1067 (struct phy_cmd[]) { /* startup */ 1068 /* Status is read once to clear old link state */ 1069 {MIIM_STATUS, miim_read, NULL}, 1070 /* Auto-negotiate */ 1071 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1072 /* Read the status */ 1073 {MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr}, 1074 {miim_end,} 1075 }, 1076 (struct phy_cmd[]) { /* shutdown */ 1077 {miim_end,} 1078 }, 1079 }; 1080 1081 static struct phy_info phy_info_BCM5482S = { 1082 0x0143bcb, 1083 "Broadcom BCM5482S", 1084 4, 1085 (struct phy_cmd[]) { /* config */ 1086 /* Reset and configure the PHY */ 1087 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1088 /* Setup read from auxilary control shadow register 7 */ 1089 {MIIM_BCM54xx_AUXCNTL, MIIM_BCM54xx_AUXCNTL_ENCODE(7), NULL}, 1090 /* Read Misc Control register and or in Ethernet@Wirespeed */ 1091 {MIIM_BCM54xx_AUXCNTL, 0, &mii_BCM54xx_wirespeed}, 1092 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1093 {miim_end,} 1094 }, 1095 (struct phy_cmd[]) { /* startup */ 1096 /* Status is read once to clear old link state */ 1097 {MIIM_STATUS, miim_read, NULL}, 1098 /* Auto-negotiate */ 1099 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1100 /* Read the status */ 1101 {MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr}, 1102 {miim_end,} 1103 }, 1104 (struct phy_cmd[]) { /* shutdown */ 1105 {miim_end,} 1106 }, 1107 }; 1108 1109 static struct phy_info phy_info_M88E1011S = { 1110 0x01410c6, 1111 "Marvell 88E1011S", 1112 4, 1113 (struct phy_cmd[]){ /* config */ 1114 /* Reset and configure the PHY */ 1115 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1116 {0x1d, 0x1f, NULL}, 1117 {0x1e, 0x200c, NULL}, 1118 {0x1d, 0x5, NULL}, 1119 {0x1e, 0x0, NULL}, 1120 {0x1e, 0x100, NULL}, 1121 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, 1122 {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, 1123 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1124 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1125 {miim_end,} 1126 }, 1127 (struct phy_cmd[]){ /* startup */ 1128 /* Status is read once to clear old link state */ 1129 {MIIM_STATUS, miim_read, NULL}, 1130 /* Auto-negotiate */ 1131 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1132 /* Read the status */ 1133 {MIIM_88E1011_PHY_STATUS, miim_read, 1134 &mii_parse_88E1011_psr}, 1135 {miim_end,} 1136 }, 1137 (struct phy_cmd[]){ /* shutdown */ 1138 {miim_end,} 1139 }, 1140 }; 1141 1142 static struct phy_info phy_info_M88E1111S = { 1143 0x01410cc, 1144 "Marvell 88E1111S", 1145 4, 1146 (struct phy_cmd[]){ /* config */ 1147 /* Reset and configure the PHY */ 1148 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1149 {0x1b, 0x848f, &mii_m88e1111s_setmode}, 1150 {0x14, 0x0cd2, NULL}, /* Delay RGMII TX and RX */ 1151 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, 1152 {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, 1153 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1154 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1155 {miim_end,} 1156 }, 1157 (struct phy_cmd[]){ /* startup */ 1158 /* Status is read once to clear old link state */ 1159 {MIIM_STATUS, miim_read, NULL}, 1160 /* Auto-negotiate */ 1161 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1162 /* Read the status */ 1163 {MIIM_88E1011_PHY_STATUS, miim_read, 1164 &mii_parse_88E1011_psr}, 1165 {miim_end,} 1166 }, 1167 (struct phy_cmd[]){ /* shutdown */ 1168 {miim_end,} 1169 }, 1170 }; 1171 1172 static struct phy_info phy_info_M88E1118 = { 1173 0x01410e1, 1174 "Marvell 88E1118", 1175 4, 1176 (struct phy_cmd[]){ /* config */ 1177 /* Reset and configure the PHY */ 1178 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1179 {0x16, 0x0002, NULL}, /* Change Page Number */ 1180 {0x15, 0x1070, NULL}, /* Delay RGMII TX and RX */ 1181 {0x16, 0x0003, NULL}, /* Change Page Number */ 1182 {0x10, 0x021e, NULL}, /* Adjust LED control */ 1183 {0x16, 0x0000, NULL}, /* Change Page Number */ 1184 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, 1185 {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, 1186 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1187 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1188 {miim_end,} 1189 }, 1190 (struct phy_cmd[]){ /* startup */ 1191 {0x16, 0x0000, NULL}, /* Change Page Number */ 1192 /* Status is read once to clear old link state */ 1193 {MIIM_STATUS, miim_read, NULL}, 1194 /* Auto-negotiate */ 1195 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1196 /* Read the status */ 1197 {MIIM_88E1011_PHY_STATUS, miim_read, 1198 &mii_parse_88E1011_psr}, 1199 {miim_end,} 1200 }, 1201 (struct phy_cmd[]){ /* shutdown */ 1202 {miim_end,} 1203 }, 1204 }; 1205 1206 /* 1207 * Since to access LED register we need do switch the page, we 1208 * do LED configuring in the miim_read-like function as follows 1209 */ 1210 static uint mii_88E1121_set_led (uint mii_reg, struct tsec_private *priv) 1211 { 1212 uint pg; 1213 1214 /* Switch the page to access the led register */ 1215 pg = read_phy_reg(priv, MIIM_88E1121_PHY_PAGE); 1216 write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, MIIM_88E1121_PHY_LED_PAGE); 1217 1218 /* Configure leds */ 1219 write_phy_reg(priv, MIIM_88E1121_PHY_LED_CTRL, 1220 MIIM_88E1121_PHY_LED_DEF); 1221 1222 /* Restore the page pointer */ 1223 write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, pg); 1224 return 0; 1225 } 1226 1227 static struct phy_info phy_info_M88E1121R = { 1228 0x01410cb, 1229 "Marvell 88E1121R", 1230 4, 1231 (struct phy_cmd[]){ /* config */ 1232 /* Reset and configure the PHY */ 1233 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1234 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, 1235 {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, 1236 /* Configure leds */ 1237 {MIIM_88E1121_PHY_LED_CTRL, miim_read, 1238 &mii_88E1121_set_led}, 1239 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1240 /* Disable IRQs and de-assert interrupt */ 1241 {MIIM_88E1121_PHY_IRQ_EN, 0, NULL}, 1242 {MIIM_88E1121_PHY_IRQ_STATUS, miim_read, NULL}, 1243 {miim_end,} 1244 }, 1245 (struct phy_cmd[]){ /* startup */ 1246 /* Status is read once to clear old link state */ 1247 {MIIM_STATUS, miim_read, NULL}, 1248 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1249 {MIIM_STATUS, miim_read, &mii_parse_link}, 1250 {miim_end,} 1251 }, 1252 (struct phy_cmd[]){ /* shutdown */ 1253 {miim_end,} 1254 }, 1255 }; 1256 1257 static unsigned int m88e1145_setmode(uint mii_reg, struct tsec_private *priv) 1258 { 1259 uint mii_data = read_phy_reg(priv, mii_reg); 1260 1261 /* Setting MIIM_88E1145_PHY_EXT_CR */ 1262 if (priv->flags & TSEC_REDUCED) 1263 return mii_data | 1264 MIIM_M88E1145_RGMII_RX_DELAY | MIIM_M88E1145_RGMII_TX_DELAY; 1265 else 1266 return mii_data; 1267 } 1268 1269 static struct phy_info phy_info_M88E1145 = { 1270 0x01410cd, 1271 "Marvell 88E1145", 1272 4, 1273 (struct phy_cmd[]){ /* config */ 1274 /* Reset the PHY */ 1275 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1276 1277 /* Errata E0, E1 */ 1278 {29, 0x001b, NULL}, 1279 {30, 0x418f, NULL}, 1280 {29, 0x0016, NULL}, 1281 {30, 0xa2da, NULL}, 1282 1283 /* Configure the PHY */ 1284 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, 1285 {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, 1286 {MIIM_88E1011_PHY_SCR, MIIM_88E1011_PHY_MDI_X_AUTO, 1287 NULL}, 1288 {MIIM_88E1145_PHY_EXT_CR, 0, &m88e1145_setmode}, 1289 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1290 {MIIM_CONTROL, MIIM_CONTROL_INIT, NULL}, 1291 {miim_end,} 1292 }, 1293 (struct phy_cmd[]){ /* startup */ 1294 /* Status is read once to clear old link state */ 1295 {MIIM_STATUS, miim_read, NULL}, 1296 /* Auto-negotiate */ 1297 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1298 {MIIM_88E1111_PHY_LED_CONTROL, 1299 MIIM_88E1111_PHY_LED_DIRECT, NULL}, 1300 /* Read the Status */ 1301 {MIIM_88E1011_PHY_STATUS, miim_read, 1302 &mii_parse_88E1011_psr}, 1303 {miim_end,} 1304 }, 1305 (struct phy_cmd[]){ /* shutdown */ 1306 {miim_end,} 1307 }, 1308 }; 1309 1310 static struct phy_info phy_info_cis8204 = { 1311 0x3f11, 1312 "Cicada Cis8204", 1313 6, 1314 (struct phy_cmd[]){ /* config */ 1315 /* Override PHY config settings */ 1316 {MIIM_CIS8201_AUX_CONSTAT, 1317 MIIM_CIS8201_AUXCONSTAT_INIT, NULL}, 1318 /* Configure some basic stuff */ 1319 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1320 {MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT, 1321 &mii_cis8204_fixled}, 1322 {MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT, 1323 &mii_cis8204_setmode}, 1324 {miim_end,} 1325 }, 1326 (struct phy_cmd[]){ /* startup */ 1327 /* Read the Status (2x to make sure link is right) */ 1328 {MIIM_STATUS, miim_read, NULL}, 1329 /* Auto-negotiate */ 1330 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1331 /* Read the status */ 1332 {MIIM_CIS8201_AUX_CONSTAT, miim_read, 1333 &mii_parse_cis8201}, 1334 {miim_end,} 1335 }, 1336 (struct phy_cmd[]){ /* shutdown */ 1337 {miim_end,} 1338 }, 1339 }; 1340 1341 /* Cicada 8201 */ 1342 static struct phy_info phy_info_cis8201 = { 1343 0xfc41, 1344 "CIS8201", 1345 4, 1346 (struct phy_cmd[]){ /* config */ 1347 /* Override PHY config settings */ 1348 {MIIM_CIS8201_AUX_CONSTAT, 1349 MIIM_CIS8201_AUXCONSTAT_INIT, NULL}, 1350 /* Set up the interface mode */ 1351 {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, 1352 NULL}, 1353 /* Configure some basic stuff */ 1354 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1355 {miim_end,} 1356 }, 1357 (struct phy_cmd[]){ /* startup */ 1358 /* Read the Status (2x to make sure link is right) */ 1359 {MIIM_STATUS, miim_read, NULL}, 1360 /* Auto-negotiate */ 1361 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1362 /* Read the status */ 1363 {MIIM_CIS8201_AUX_CONSTAT, miim_read, 1364 &mii_parse_cis8201}, 1365 {miim_end,} 1366 }, 1367 (struct phy_cmd[]){ /* shutdown */ 1368 {miim_end,} 1369 }, 1370 }; 1371 1372 static struct phy_info phy_info_VSC8211 = { 1373 0xfc4b, 1374 "Vitesse VSC8211", 1375 4, 1376 (struct phy_cmd[]) { /* config */ 1377 /* Override PHY config settings */ 1378 {MIIM_CIS8201_AUX_CONSTAT, 1379 MIIM_CIS8201_AUXCONSTAT_INIT, NULL}, 1380 /* Set up the interface mode */ 1381 {MIIM_CIS8201_EXT_CON1, 1382 MIIM_CIS8201_EXTCON1_INIT, NULL}, 1383 /* Configure some basic stuff */ 1384 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1385 {miim_end,} 1386 }, 1387 (struct phy_cmd[]) { /* startup */ 1388 /* Read the Status (2x to make sure link is right) */ 1389 {MIIM_STATUS, miim_read, NULL}, 1390 /* Auto-negotiate */ 1391 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1392 /* Read the status */ 1393 {MIIM_CIS8201_AUX_CONSTAT, miim_read, 1394 &mii_parse_cis8201}, 1395 {miim_end,} 1396 }, 1397 (struct phy_cmd[]) { /* shutdown */ 1398 {miim_end,} 1399 }, 1400 }; 1401 1402 static struct phy_info phy_info_VSC8244 = { 1403 0x3f1b, 1404 "Vitesse VSC8244", 1405 6, 1406 (struct phy_cmd[]){ /* config */ 1407 /* Override PHY config settings */ 1408 /* Configure some basic stuff */ 1409 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1410 {miim_end,} 1411 }, 1412 (struct phy_cmd[]){ /* startup */ 1413 /* Read the Status (2x to make sure link is right) */ 1414 {MIIM_STATUS, miim_read, NULL}, 1415 /* Auto-negotiate */ 1416 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1417 /* Read the status */ 1418 {MIIM_VSC8244_AUX_CONSTAT, miim_read, 1419 &mii_parse_vsc8244}, 1420 {miim_end,} 1421 }, 1422 (struct phy_cmd[]){ /* shutdown */ 1423 {miim_end,} 1424 }, 1425 }; 1426 1427 static struct phy_info phy_info_VSC8641 = { 1428 0x7043, 1429 "Vitesse VSC8641", 1430 4, 1431 (struct phy_cmd[]){ /* config */ 1432 /* Configure some basic stuff */ 1433 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1434 {miim_end,} 1435 }, 1436 (struct phy_cmd[]){ /* startup */ 1437 /* Read the Status (2x to make sure link is right) */ 1438 {MIIM_STATUS, miim_read, NULL}, 1439 /* Auto-negotiate */ 1440 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1441 /* Read the status */ 1442 {MIIM_VSC8244_AUX_CONSTAT, miim_read, 1443 &mii_parse_vsc8244}, 1444 {miim_end,} 1445 }, 1446 (struct phy_cmd[]){ /* shutdown */ 1447 {miim_end,} 1448 }, 1449 }; 1450 1451 static struct phy_info phy_info_VSC8221 = { 1452 0xfc55, 1453 "Vitesse VSC8221", 1454 4, 1455 (struct phy_cmd[]){ /* config */ 1456 /* Configure some basic stuff */ 1457 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1458 {miim_end,} 1459 }, 1460 (struct phy_cmd[]){ /* startup */ 1461 /* Read the Status (2x to make sure link is right) */ 1462 {MIIM_STATUS, miim_read, NULL}, 1463 /* Auto-negotiate */ 1464 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1465 /* Read the status */ 1466 {MIIM_VSC8244_AUX_CONSTAT, miim_read, 1467 &mii_parse_vsc8244}, 1468 {miim_end,} 1469 }, 1470 (struct phy_cmd[]){ /* shutdown */ 1471 {miim_end,} 1472 }, 1473 }; 1474 1475 static struct phy_info phy_info_VSC8601 = { 1476 0x00007042, 1477 "Vitesse VSC8601", 1478 4, 1479 (struct phy_cmd[]){ /* config */ 1480 /* Override PHY config settings */ 1481 /* Configure some basic stuff */ 1482 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1483 #ifdef CONFIG_SYS_VSC8601_SKEWFIX 1484 {MIIM_VSC8601_EPHY_CON,MIIM_VSC8601_EPHY_CON_INIT_SKEW,NULL}, 1485 #if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX) 1486 {MIIM_EXT_PAGE_ACCESS,1,NULL}, 1487 #define VSC8101_SKEW (CONFIG_SYS_VSC8601_SKEW_TX<<14)|(CONFIG_SYS_VSC8601_SKEW_RX<<12) 1488 {MIIM_VSC8601_SKEW_CTRL,VSC8101_SKEW,NULL}, 1489 {MIIM_EXT_PAGE_ACCESS,0,NULL}, 1490 #endif 1491 #endif 1492 {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, 1493 {MIIM_CONTROL, MIIM_CONTROL_RESTART, &mii_cr_init}, 1494 {miim_end,} 1495 }, 1496 (struct phy_cmd[]){ /* startup */ 1497 /* Read the Status (2x to make sure link is right) */ 1498 {MIIM_STATUS, miim_read, NULL}, 1499 /* Auto-negotiate */ 1500 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1501 /* Read the status */ 1502 {MIIM_VSC8244_AUX_CONSTAT, miim_read, 1503 &mii_parse_vsc8244}, 1504 {miim_end,} 1505 }, 1506 (struct phy_cmd[]){ /* shutdown */ 1507 {miim_end,} 1508 }, 1509 }; 1510 1511 1512 static struct phy_info phy_info_dm9161 = { 1513 0x0181b88, 1514 "Davicom DM9161E", 1515 4, 1516 (struct phy_cmd[]){ /* config */ 1517 {MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL}, 1518 /* Do not bypass the scrambler/descrambler */ 1519 {MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL}, 1520 /* Clear 10BTCSR to default */ 1521 {MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, 1522 NULL}, 1523 /* Configure some basic stuff */ 1524 {MIIM_CONTROL, MIIM_CR_INIT, NULL}, 1525 /* Restart Auto Negotiation */ 1526 {MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL}, 1527 {miim_end,} 1528 }, 1529 (struct phy_cmd[]){ /* startup */ 1530 /* Status is read once to clear old link state */ 1531 {MIIM_STATUS, miim_read, NULL}, 1532 /* Auto-negotiate */ 1533 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1534 /* Read the status */ 1535 {MIIM_DM9161_SCSR, miim_read, 1536 &mii_parse_dm9161_scsr}, 1537 {miim_end,} 1538 }, 1539 (struct phy_cmd[]){ /* shutdown */ 1540 {miim_end,} 1541 }, 1542 }; 1543 /* a generic flavor. */ 1544 static struct phy_info phy_info_generic = { 1545 0, 1546 "Unknown/Generic PHY", 1547 32, 1548 (struct phy_cmd[]) { /* config */ 1549 {PHY_BMCR, PHY_BMCR_RESET, NULL}, 1550 {PHY_BMCR, PHY_BMCR_AUTON|PHY_BMCR_RST_NEG, NULL}, 1551 {miim_end,} 1552 }, 1553 (struct phy_cmd[]) { /* startup */ 1554 {PHY_BMSR, miim_read, NULL}, 1555 {PHY_BMSR, miim_read, &mii_parse_sr}, 1556 {PHY_BMSR, miim_read, &mii_parse_link}, 1557 {miim_end,} 1558 }, 1559 (struct phy_cmd[]) { /* shutdown */ 1560 {miim_end,} 1561 } 1562 }; 1563 1564 1565 static uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv) 1566 { 1567 unsigned int speed; 1568 if (priv->link) { 1569 speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK; 1570 1571 switch (speed) { 1572 case MIIM_LXT971_SR2_10HDX: 1573 priv->speed = 10; 1574 priv->duplexity = 0; 1575 break; 1576 case MIIM_LXT971_SR2_10FDX: 1577 priv->speed = 10; 1578 priv->duplexity = 1; 1579 break; 1580 case MIIM_LXT971_SR2_100HDX: 1581 priv->speed = 100; 1582 priv->duplexity = 0; 1583 break; 1584 default: 1585 priv->speed = 100; 1586 priv->duplexity = 1; 1587 } 1588 } else { 1589 priv->speed = 0; 1590 priv->duplexity = 0; 1591 } 1592 1593 return 0; 1594 } 1595 1596 static struct phy_info phy_info_lxt971 = { 1597 0x0001378e, 1598 "LXT971", 1599 4, 1600 (struct phy_cmd[]){ /* config */ 1601 {MIIM_CR, MIIM_CR_INIT, mii_cr_init}, /* autonegotiate */ 1602 {miim_end,} 1603 }, 1604 (struct phy_cmd[]){ /* startup - enable interrupts */ 1605 /* { 0x12, 0x00f2, NULL }, */ 1606 {MIIM_STATUS, miim_read, NULL}, 1607 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1608 {MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2}, 1609 {miim_end,} 1610 }, 1611 (struct phy_cmd[]){ /* shutdown - disable interrupts */ 1612 {miim_end,} 1613 }, 1614 }; 1615 1616 /* Parse the DP83865's link and auto-neg status register for speed and duplex 1617 * information 1618 */ 1619 static uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv) 1620 { 1621 switch (mii_reg & MIIM_DP83865_SPD_MASK) { 1622 1623 case MIIM_DP83865_SPD_1000: 1624 priv->speed = 1000; 1625 break; 1626 1627 case MIIM_DP83865_SPD_100: 1628 priv->speed = 100; 1629 break; 1630 1631 default: 1632 priv->speed = 10; 1633 break; 1634 1635 } 1636 1637 if (mii_reg & MIIM_DP83865_DPX_FULL) 1638 priv->duplexity = 1; 1639 else 1640 priv->duplexity = 0; 1641 1642 return 0; 1643 } 1644 1645 static struct phy_info phy_info_dp83865 = { 1646 0x20005c7, 1647 "NatSemi DP83865", 1648 4, 1649 (struct phy_cmd[]){ /* config */ 1650 {MIIM_CONTROL, MIIM_DP83865_CR_INIT, NULL}, 1651 {miim_end,} 1652 }, 1653 (struct phy_cmd[]){ /* startup */ 1654 /* Status is read once to clear old link state */ 1655 {MIIM_STATUS, miim_read, NULL}, 1656 /* Auto-negotiate */ 1657 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1658 /* Read the link and auto-neg status */ 1659 {MIIM_DP83865_LANR, miim_read, 1660 &mii_parse_dp83865_lanr}, 1661 {miim_end,} 1662 }, 1663 (struct phy_cmd[]){ /* shutdown */ 1664 {miim_end,} 1665 }, 1666 }; 1667 1668 static struct phy_info phy_info_rtl8211b = { 1669 0x001cc91, 1670 "RealTek RTL8211B", 1671 4, 1672 (struct phy_cmd[]){ /* config */ 1673 /* Reset and configure the PHY */ 1674 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1675 {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, 1676 {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, 1677 {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, 1678 {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, 1679 {miim_end,} 1680 }, 1681 (struct phy_cmd[]){ /* startup */ 1682 /* Status is read once to clear old link state */ 1683 {MIIM_STATUS, miim_read, NULL}, 1684 /* Auto-negotiate */ 1685 {MIIM_STATUS, miim_read, &mii_parse_sr}, 1686 /* Read the status */ 1687 {MIIM_RTL8211B_PHY_STATUS, miim_read, &mii_parse_RTL8211B_sr}, 1688 {miim_end,} 1689 }, 1690 (struct phy_cmd[]){ /* shutdown */ 1691 {miim_end,} 1692 }, 1693 }; 1694 1695 static struct phy_info *phy_info[] = { 1696 &phy_info_cis8204, 1697 &phy_info_cis8201, 1698 &phy_info_BCM5461S, 1699 &phy_info_BCM5464S, 1700 &phy_info_BCM5482S, 1701 &phy_info_M88E1011S, 1702 &phy_info_M88E1111S, 1703 &phy_info_M88E1118, 1704 &phy_info_M88E1121R, 1705 &phy_info_M88E1145, 1706 &phy_info_M88E1149S, 1707 &phy_info_dm9161, 1708 &phy_info_lxt971, 1709 &phy_info_VSC8211, 1710 &phy_info_VSC8244, 1711 &phy_info_VSC8601, 1712 &phy_info_VSC8641, 1713 &phy_info_VSC8221, 1714 &phy_info_dp83865, 1715 &phy_info_rtl8211b, 1716 &phy_info_generic, /* must be last; has ID 0 and 32 bit mask */ 1717 NULL 1718 }; 1719 1720 /* Grab the identifier of the device's PHY, and search through 1721 * all of the known PHYs to see if one matches. If so, return 1722 * it, if not, return NULL 1723 */ 1724 static struct phy_info *get_phy_info(struct eth_device *dev) 1725 { 1726 struct tsec_private *priv = (struct tsec_private *)dev->priv; 1727 uint phy_reg, phy_ID; 1728 int i; 1729 struct phy_info *theInfo = NULL; 1730 1731 /* Grab the bits from PHYIR1, and put them in the upper half */ 1732 phy_reg = read_phy_reg(priv, MIIM_PHYIR1); 1733 phy_ID = (phy_reg & 0xffff) << 16; 1734 1735 /* Grab the bits from PHYIR2, and put them in the lower half */ 1736 phy_reg = read_phy_reg(priv, MIIM_PHYIR2); 1737 phy_ID |= (phy_reg & 0xffff); 1738 1739 /* loop through all the known PHY types, and find one that */ 1740 /* matches the ID we read from the PHY. */ 1741 for (i = 0; phy_info[i]; i++) { 1742 if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) { 1743 theInfo = phy_info[i]; 1744 break; 1745 } 1746 } 1747 1748 if (theInfo == &phy_info_generic) { 1749 printf("%s: No support for PHY id %x; assuming generic\n", dev->name, phy_ID); 1750 } else { 1751 debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID); 1752 } 1753 1754 return theInfo; 1755 } 1756 1757 /* Execute the given series of commands on the given device's 1758 * PHY, running functions as necessary 1759 */ 1760 static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd) 1761 { 1762 int i; 1763 uint result; 1764 volatile tsec_mdio_t *phyregs = priv->phyregs; 1765 1766 phyregs->miimcfg = MIIMCFG_RESET; 1767 1768 phyregs->miimcfg = MIIMCFG_INIT_VALUE; 1769 1770 while (phyregs->miimind & MIIMIND_BUSY) ; 1771 1772 for (i = 0; cmd->mii_reg != miim_end; i++) { 1773 if (cmd->mii_data == miim_read) { 1774 result = read_phy_reg(priv, cmd->mii_reg); 1775 1776 if (cmd->funct != NULL) 1777 (*(cmd->funct)) (result, priv); 1778 1779 } else { 1780 if (cmd->funct != NULL) 1781 result = (*(cmd->funct)) (cmd->mii_reg, priv); 1782 else 1783 result = cmd->mii_data; 1784 1785 write_phy_reg(priv, cmd->mii_reg, result); 1786 1787 } 1788 cmd++; 1789 } 1790 } 1791 1792 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ 1793 && !defined(BITBANGMII) 1794 1795 /* 1796 * Read a MII PHY register. 1797 * 1798 * Returns: 1799 * 0 on success 1800 */ 1801 static int tsec_miiphy_read(char *devname, unsigned char addr, 1802 unsigned char reg, unsigned short *value) 1803 { 1804 unsigned short ret; 1805 struct tsec_private *priv = privlist[0]; 1806 1807 if (NULL == priv) { 1808 printf("Can't read PHY at address %d\n", addr); 1809 return -1; 1810 } 1811 1812 ret = (unsigned short)tsec_local_mdio_read(priv->phyregs, addr, reg); 1813 *value = ret; 1814 1815 return 0; 1816 } 1817 1818 /* 1819 * Write a MII PHY register. 1820 * 1821 * Returns: 1822 * 0 on success 1823 */ 1824 static int tsec_miiphy_write(char *devname, unsigned char addr, 1825 unsigned char reg, unsigned short value) 1826 { 1827 struct tsec_private *priv = privlist[0]; 1828 1829 if (NULL == priv) { 1830 printf("Can't write PHY at address %d\n", addr); 1831 return -1; 1832 } 1833 1834 tsec_local_mdio_write(priv->phyregs, addr, reg, value); 1835 1836 return 0; 1837 } 1838 1839 #endif 1840 1841 #ifdef CONFIG_MCAST_TFTP 1842 1843 /* CREDITS: linux gianfar driver, slightly adjusted... thanx. */ 1844 1845 /* Set the appropriate hash bit for the given addr */ 1846 1847 /* The algorithm works like so: 1848 * 1) Take the Destination Address (ie the multicast address), and 1849 * do a CRC on it (little endian), and reverse the bits of the 1850 * result. 1851 * 2) Use the 8 most significant bits as a hash into a 256-entry 1852 * table. The table is controlled through 8 32-bit registers: 1853 * gaddr0-7. gaddr0's MSB is entry 0, and gaddr7's LSB is 1854 * gaddr7. This means that the 3 most significant bits in the 1855 * hash index which gaddr register to use, and the 5 other bits 1856 * indicate which bit (assuming an IBM numbering scheme, which 1857 * for PowerPC (tm) is usually the case) in the tregister holds 1858 * the entry. */ 1859 static int 1860 tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set) 1861 { 1862 struct tsec_private *priv = privlist[1]; 1863 volatile tsec_t *regs = priv->regs; 1864 volatile u32 *reg_array, value; 1865 u8 result, whichbit, whichreg; 1866 1867 result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff); 1868 whichbit = result & 0x1f; /* the 5 LSB = which bit to set */ 1869 whichreg = result >> 5; /* the 3 MSB = which reg to set it in */ 1870 value = (1 << (31-whichbit)); 1871 1872 reg_array = &(regs->hash.gaddr0); 1873 1874 if (set) { 1875 reg_array[whichreg] |= value; 1876 } else { 1877 reg_array[whichreg] &= ~value; 1878 } 1879 return 0; 1880 } 1881 #endif /* Multicast TFTP ? */ 1882