1 /* 2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * This file may contain confidential information of Nvidia 8 * and should not be distributed in source form without approval 9 * from Sun Legal. 10 */ 11 12 #pragma ident "%Z%%M% %I% %E% SMI" 13 14 #include "nge.h" 15 16 #undef NGE_DBG 17 #define NGE_DBG NGE_DBG_MII /* debug flag for this code */ 18 19 /* 20 * The arrays below can be indexed by the MODE bits from the mac2phy 21 * register to determine the current speed/duplex settings. 22 */ 23 static const int16_t nge_copper_link_speed[] = { 24 0, /* MII_AUX_STATUS_MODE_NONE */ 25 10, /* MII_AUX_STAT0,US_MODE_10 */ 26 100, /* MII_AUX_STAT0,US_MODE_100 */ 27 1000, /* MII_AUX_STAT0,US_MODE_1000 */ 28 }; 29 30 static const int8_t nge_copper_link_duplex[] = { 31 LINK_DUPLEX_UNKNOWN, /* MII_DUPLEX_NONE */ 32 LINK_DUPLEX_HALF, /* MII_DUPLEX_HALF */ 33 LINK_DUPLEX_FULL, /* MII_DUPLEX_FULL */ 34 }; 35 36 37 static uint16_t nge_mii_access(nge_t *ngep, nge_regno_t regno, 38 uint16_t data, uint32_t cmd); 39 #pragma inline(nge_mii_access) 40 41 static uint16_t 42 nge_mii_access(nge_t *ngep, nge_regno_t regno, uint16_t data, uint32_t cmd) 43 { 44 uint16_t tries; 45 uint16_t mdio_data; 46 nge_mdio_adr mdio_adr; 47 nge_mintr_src intr_src; 48 49 NGE_TRACE(("nge_mii_access($%p, 0x%lx, 0x%x, 0x%x)", 50 (void *)ngep, regno, data, cmd)); 51 52 /* 53 * Clear the privous interrupt event 54 */ 55 intr_src.src_val = nge_reg_get8(ngep, NGE_MINTR_SRC); 56 nge_reg_put8(ngep, NGE_MINTR_SRC, intr_src.src_val); 57 58 /* 59 * Check whether the current operation has been finished 60 */ 61 mdio_adr.adr_val = nge_reg_get16(ngep, NGE_MDIO_ADR); 62 for (tries = 0; tries < 30; tries ++) { 63 if (mdio_adr.adr_bits.mdio_clc == NGE_CLEAR) 64 break; 65 drv_usecwait(10); 66 mdio_adr.adr_val = nge_reg_get16(ngep, NGE_MDIO_ADR); 67 } 68 69 /* 70 * The current operation can not be finished successfully 71 * The driver should halt the current operation 72 */ 73 if (tries == 30) { 74 mdio_adr.adr_bits.mdio_clc = NGE_SET; 75 nge_reg_put16(ngep, NGE_MDIO_ADR, mdio_adr.adr_val); 76 drv_usecwait(100); 77 } 78 79 /* 80 * Assemble the operation cmd 81 */ 82 mdio_adr.adr_bits.phy_reg = regno; 83 mdio_adr.adr_bits.phy_adr = ngep->phy_xmii_addr; 84 mdio_adr.adr_bits.mdio_rw = (cmd == NGE_MDIO_WRITE) ? 1 : 0; 85 86 87 if (cmd == NGE_MDIO_WRITE) 88 nge_reg_put16(ngep, NGE_MDIO_DATA, data); 89 90 nge_reg_put16(ngep, NGE_MDIO_ADR, mdio_adr.adr_val); 91 92 /* 93 * To check whether the read/write operation is finished 94 */ 95 for (tries = 0; tries < 300; tries ++) { 96 drv_usecwait(10); 97 mdio_adr.adr_val = nge_reg_get16(ngep, NGE_MDIO_ADR); 98 if (mdio_adr.adr_bits.mdio_clc == NGE_CLEAR) 99 break; 100 } 101 if (tries == 300) 102 return ((uint16_t)~0); 103 104 /* 105 * Read the data from MDIO data register 106 */ 107 if (cmd == NGE_MDIO_READ) 108 mdio_data = nge_reg_get16(ngep, NGE_MDIO_DATA); 109 110 /* 111 * To check whether the read/write operation is valid 112 */ 113 intr_src.src_val = nge_reg_get8(ngep, NGE_MINTR_SRC); 114 nge_reg_put8(ngep, NGE_MINTR_SRC, intr_src.src_val); 115 if (intr_src.src_bits.mrei == NGE_SET) 116 return ((uint16_t)~0); 117 118 return (mdio_data); 119 } 120 121 uint16_t nge_mii_get16(nge_t *ngep, nge_regno_t regno); 122 #pragma inline(nge_mii_get16) 123 124 uint16_t 125 nge_mii_get16(nge_t *ngep, nge_regno_t regno) 126 { 127 128 return (nge_mii_access(ngep, regno, 0, NGE_MDIO_READ)); 129 } 130 131 void nge_mii_put16(nge_t *ngep, nge_regno_t regno, uint16_t data); 132 #pragma inline(nge_mii_put16) 133 134 void 135 nge_mii_put16(nge_t *ngep, nge_regno_t regno, uint16_t data) 136 { 137 138 (void) nge_mii_access(ngep, regno, data, NGE_MDIO_WRITE); 139 } 140 141 /* 142 * Basic low-level function to probe for a PHY 143 * 144 * Returns TRUE if the PHY responds with valid data, FALSE otherwise 145 */ 146 static boolean_t 147 nge_phy_probe(nge_t *ngep) 148 { 149 int i; 150 uint16_t phy_status; 151 uint16_t phyidh; 152 uint16_t phyidl; 153 154 NGE_TRACE(("nge_phy_probe($%p)", (void *)ngep)); 155 156 /* 157 * Scan the phys to find the right address 158 * of the phy 159 * 160 * Probe maximum for 32 phy addresses 161 */ 162 for (i = 0; i < NGE_PHY_NUMBER; i++) { 163 ngep->phy_xmii_addr = i; 164 /* 165 * Read the MII_STATUS register twice, in 166 * order to clear any sticky bits (but they should 167 * have been cleared by the RESET, I think). 168 */ 169 phy_status = nge_mii_get16(ngep, MII_STATUS); 170 phy_status = nge_mii_get16(ngep, MII_STATUS); 171 if (phy_status != 0xffff) { 172 phyidh = nge_mii_get16(ngep, MII_PHYIDH); 173 phyidl = nge_mii_get16(ngep, MII_PHYIDL); 174 ngep->phy_id = 175 (((uint32_t)phyidh << 16) |(phyidl & MII_IDL_MASK)); 176 NGE_DEBUG(("nge_phy_probe: status 0x%x, phy id 0x%x", 177 phy_status, ngep->phy_id)); 178 179 return (B_TRUE); 180 } 181 } 182 183 return (B_FALSE); 184 } 185 186 187 /* 188 * Basic low-level function to powerup the phy and remove the isolation 189 */ 190 191 static boolean_t 192 nge_phy_recover(nge_t *ngep) 193 { 194 uint16_t control; 195 uint16_t count; 196 197 NGE_TRACE(("nge_phy_recover($%p)", (void *)ngep)); 198 control = nge_mii_get16(ngep, MII_CONTROL); 199 control &= ~(MII_CONTROL_PWRDN | MII_CONTROL_ISOLATE); 200 nge_mii_put16(ngep, MII_CONTROL, control); 201 for (count = 0; ++count < 10; ) { 202 drv_usecwait(5); 203 control = nge_mii_get16(ngep, MII_CONTROL); 204 if (BIC(control, MII_CONTROL_PWRDN)) 205 return (B_TRUE); 206 } 207 208 return (B_FALSE); 209 } 210 /* 211 * Basic low-level function to reset the PHY. 212 * Doesn't incorporate any special-case workarounds. 213 * 214 * Returns TRUE on success, FALSE if the RESET bit doesn't clear 215 */ 216 boolean_t 217 nge_phy_reset(nge_t *ngep) 218 { 219 uint16_t control; 220 uint_t count; 221 222 NGE_TRACE(("nge_phy_reset($%p)", (void *)ngep)); 223 224 ASSERT(mutex_owned(ngep->genlock)); 225 226 /* 227 * Set the PHY RESET bit, then wait up to 5 ms for it to self-clear 228 */ 229 control = nge_mii_get16(ngep, MII_CONTROL); 230 control |= MII_CONTROL_RESET; 231 nge_mii_put16(ngep, MII_CONTROL, control); 232 drv_usecwait(30); 233 for (count = 0; ++count < 10; ) { 234 drv_usecwait(5); 235 control = nge_mii_get16(ngep, MII_CONTROL); 236 if (BIC(control, MII_CONTROL_RESET)) 237 return (B_TRUE); 238 } 239 NGE_DEBUG(("nge_phy_reset: FAILED, control now 0x%x", control)); 240 241 return (B_FALSE); 242 } 243 244 static void 245 nge_phy_restart(nge_t *ngep) 246 { 247 uint16_t mii_reg; 248 249 (void) nge_phy_recover(ngep); 250 (void) nge_phy_reset(ngep); 251 if (PHY_MANUFACTURER(ngep->phy_id) == MII_ID_CICADA) { 252 if (ngep->phy_mode == RGMII_IN) { 253 mii_reg = nge_mii_get16(ngep, 254 MII_CICADA_EXT_CONTROL); 255 mii_reg &= ~(MII_CICADA_MODE_SELECT_BITS 256 | MII_CICADA_POWER_SUPPLY_BITS); 257 mii_reg |= (MII_CICADA_MODE_SELECT_RGMII 258 | MII_CICADA_POWER_SUPPLY_2_5V); 259 nge_mii_put16(ngep, MII_CICADA_EXT_CONTROL, mii_reg); 260 261 mii_reg = nge_mii_get16(ngep, 262 MII_CICADA_AUXCTRL_STATUS); 263 mii_reg |= MII_CICADA_PIN_PRORITY_SETTING; 264 nge_mii_put16(ngep, MII_CICADA_AUXCTRL_STATUS, 265 mii_reg); 266 } else { 267 mii_reg = nge_mii_get16(ngep, 268 MII_CICADA_10BASET_CONTROL); 269 mii_reg |= MII_CICADA_DISABLE_ECHO_MODE; 270 nge_mii_put16(ngep, 271 MII_CICADA_10BASET_CONTROL, mii_reg); 272 273 mii_reg = nge_mii_get16(ngep, 274 MII_CICADA_BYPASS_CONTROL); 275 mii_reg &= (~CICADA_125MHZ_CLOCK_ENABLE); 276 nge_mii_put16(ngep, MII_CICADA_BYPASS_CONTROL, mii_reg); 277 } 278 } 279 } 280 281 /* 282 * Synchronise the (copper) PHY's speed/duplex/autonegotiation capabilities 283 * and advertisements with the required settings as specified by the various 284 * param_* variables that can be poked via the NDD interface. 285 * 286 * We always reset the PHY and reprogram *all* the relevant registers, 287 * not just those changed. This should cause the link to go down, and then 288 * back up again once the link is stable and autonegotiation (if enabled) 289 * is complete. We should get a link state change interrupt somewhere along 290 * the way ... 291 * 292 * NOTE: <genlock> must already be held by the caller 293 */ 294 static void 295 nge_update_copper(nge_t *ngep) 296 { 297 uint16_t control; 298 uint16_t gigctrl; 299 uint16_t anar; 300 boolean_t adv_autoneg; 301 boolean_t adv_pause; 302 boolean_t adv_asym_pause; 303 boolean_t adv_1000fdx; 304 boolean_t adv_100fdx; 305 boolean_t adv_100hdx; 306 boolean_t adv_10fdx; 307 boolean_t adv_10hdx; 308 309 NGE_TRACE(("nge_update_copper($%p)", (void *)ngep)); 310 311 ASSERT(mutex_owned(ngep->genlock)); 312 313 NGE_DEBUG(("nge_update_copper: autoneg %d " 314 "pause %d asym_pause %d " 315 "1000fdx %d " 316 "100fdx %d 100hdx %d " 317 "10fdx %d 10hdx %d ", 318 ngep->param_adv_autoneg, 319 ngep->param_adv_pause, ngep->param_adv_asym_pause, 320 ngep->param_adv_1000fdx, 321 ngep->param_adv_100fdx, ngep->param_adv_100hdx, 322 ngep->param_adv_10fdx, ngep->param_adv_10hdx)); 323 324 control = anar = gigctrl = 0; 325 326 /* 327 * PHY settings are normally based on the param_* variables, 328 * but if any loopback mode is in effect, that takes precedence. 329 * 330 * NGE supports MAC-internal loopback, PHY-internal loopback, 331 * and External loopback at a variety of speeds (with a special 332 * cable). In all cases, autoneg is turned OFF, full-duplex 333 * is turned ON, and the speed/mastership is forced. 334 */ 335 switch (ngep->param_loop_mode) { 336 case NGE_LOOP_NONE: 337 default: 338 adv_pause = ngep->param_adv_pause; 339 adv_autoneg = ngep->param_adv_autoneg; 340 adv_asym_pause = ngep->param_adv_asym_pause; 341 if (ngep->phy_mode == MII_IN) { 342 adv_1000fdx = ngep->param_adv_1000fdx = B_FALSE; 343 } 344 adv_1000fdx = ngep->param_adv_1000fdx; 345 adv_100fdx = ngep->param_adv_100fdx; 346 adv_100hdx = ngep->param_adv_100hdx; 347 adv_10fdx = ngep->param_adv_10fdx; 348 adv_10hdx = ngep->param_adv_10hdx; 349 350 break; 351 352 case NGE_LOOP_EXTERNAL_100: 353 case NGE_LOOP_EXTERNAL_10: 354 case NGE_LOOP_INTERNAL_PHY: 355 adv_autoneg = adv_pause = adv_asym_pause = B_FALSE; 356 adv_1000fdx = adv_100fdx = adv_10fdx = B_FALSE; 357 adv_100hdx = adv_10hdx = B_FALSE; 358 ngep->param_link_duplex = LINK_DUPLEX_FULL; 359 360 switch (ngep->param_loop_mode) { 361 case NGE_LOOP_EXTERNAL_100: 362 ngep->param_link_speed = 100; 363 adv_100fdx = B_TRUE; 364 break; 365 366 case NGE_LOOP_EXTERNAL_10: 367 ngep->param_link_speed = 10; 368 adv_10fdx = B_TRUE; 369 break; 370 371 case NGE_LOOP_INTERNAL_PHY: 372 ngep->param_link_speed = 1000; 373 adv_1000fdx = B_TRUE; 374 break; 375 376 } 377 } 378 NGE_DEBUG(("nge_update_copper: autoneg %d " 379 "pause %d asym_pause %d " 380 "1000fdx %d " 381 "100fdx %d 100hdx %d " 382 "10fdx %d 10hdx %d ", 383 adv_autoneg, 384 adv_pause, adv_asym_pause, 385 adv_1000fdx, 386 adv_100fdx, adv_100hdx, 387 adv_10fdx, adv_10hdx)); 388 389 /* 390 * We should have at least one technology capability set; 391 * if not, we select a default of 10Mb/s half-duplex 392 */ 393 if (!adv_1000fdx && !adv_100fdx && !adv_10fdx && 394 !adv_100hdx && !adv_10hdx) 395 adv_10hdx = B_TRUE; 396 397 /* 398 * Now transform the adv_* variables into the proper settings 399 * of the PHY registers ... 400 * 401 * If autonegotiation is (now) enabled, we want to trigger 402 * a new autonegotiation cycle once the PHY has been 403 * programmed with the capabilities to be advertised. 404 */ 405 if (adv_autoneg) 406 control |= MII_CONTROL_ANE|MII_CONTROL_RSAN; 407 408 if (adv_1000fdx) 409 control |= MII_CONTROL_1000MB|MII_CONTROL_FDUPLEX; 410 else if (adv_100fdx) 411 control |= MII_CONTROL_100MB|MII_CONTROL_FDUPLEX; 412 else if (adv_100hdx) 413 control |= MII_CONTROL_100MB; 414 else if (adv_10fdx) 415 control |= MII_CONTROL_FDUPLEX; 416 else if (adv_10hdx) 417 control |= 0; 418 else 419 { _NOTE(EMPTY); } /* Can't get here anyway ... */ 420 421 if (adv_1000fdx) 422 gigctrl |= MII_1000BT_CTL_ADV_FDX; 423 if (adv_100fdx) 424 anar |= MII_ABILITY_100BASE_TX_FD; 425 if (adv_100hdx) 426 anar |= MII_ABILITY_100BASE_TX; 427 if (adv_10fdx) 428 anar |= MII_ABILITY_10BASE_T_FD; 429 if (adv_10hdx) 430 anar |= MII_ABILITY_10BASE_T; 431 432 if (adv_pause) 433 anar |= MII_ABILITY_PAUSE; 434 if (adv_asym_pause) 435 anar |= MII_ABILITY_ASYM_PAUSE; 436 437 /* 438 * Munge in any other fixed bits we require ... 439 */ 440 anar |= MII_AN_SELECTOR_8023; 441 442 /* 443 * Restart the PHY and write the new values. 444 */ 445 nge_mii_put16(ngep, MII_AN_ADVERT, anar); 446 nge_mii_put16(ngep, MII_CONTROL, control); 447 nge_mii_put16(ngep, MII_1000BASE_T_CONTROL, gigctrl); 448 nge_phy_restart(ngep); 449 450 /* 451 * Loopback bit in control register is not reset sticky 452 * write it after PHY restart. 453 */ 454 if (ngep->param_loop_mode == NGE_LOOP_INTERNAL_PHY) { 455 control = nge_mii_get16(ngep, MII_CONTROL); 456 control |= MII_CONTROL_LOOPBACK; 457 nge_mii_put16(ngep, MII_CONTROL, control); 458 } 459 } 460 461 static boolean_t 462 nge_check_copper(nge_t *ngep) 463 { 464 uint16_t mii_status; 465 uint16_t mii_exstatus; 466 uint16_t mii_excontrol; 467 uint16_t anar; 468 uint16_t lpan; 469 uint_t speed; 470 uint_t duplex; 471 boolean_t linkup; 472 nge_mii_cs mii_cs; 473 nge_mintr_src mintr_src; 474 475 speed = UNKOWN_SPEED; 476 duplex = UNKOWN_DUPLEX; 477 /* 478 * Read the status from the PHY (which is self-clearing 479 * on read!); also read & clear the main (Ethernet) MAC status 480 * (the relevant bits of this are write-one-to-clear). 481 */ 482 mii_status = nge_mii_get16(ngep, MII_STATUS); 483 mii_cs.cs_val = nge_reg_get32(ngep, NGE_MII_CS); 484 mintr_src.src_val = nge_reg_get32(ngep, NGE_MINTR_SRC); 485 nge_reg_put32(ngep, NGE_MINTR_SRC, mintr_src.src_val); 486 487 NGE_DEBUG(("nge_check_copper: link %d/%s, MII status 0x%x " 488 "(was 0x%x)", ngep->link_state, 489 UPORDOWN(ngep->param_link_up), mii_status, 490 ngep->phy_gen_status)); 491 492 do { 493 /* 494 * If the PHY status changed, record the time 495 */ 496 switch (ngep->phy_mode) { 497 default: 498 case RGMII_IN: 499 500 /* 501 * Judge the giga speed by reading control 502 * and status register 503 */ 504 mii_excontrol = nge_mii_get16(ngep, 505 MII_1000BASE_T_CONTROL); 506 mii_exstatus = nge_mii_get16(ngep, 507 MII_1000BASE_T_STATUS); 508 if ((mii_excontrol & MII_1000BT_CTL_ADV_FDX) && 509 (mii_exstatus & MII_1000BT_STAT_LP_FDX_CAP)) { 510 speed = NGE_1000M; 511 duplex = NGE_FD; 512 } else { 513 anar = nge_mii_get16(ngep, MII_AN_ADVERT); 514 lpan = nge_mii_get16(ngep, MII_AN_LPABLE); 515 if (lpan != 0) 516 anar = (anar & lpan); 517 if (anar & MII_100BASET_FD) { 518 speed = NGE_100M; 519 duplex = NGE_FD; 520 } else if (anar & MII_100BASET_HD) { 521 speed = NGE_100M; 522 duplex = NGE_HD; 523 } else if (anar & MII_10BASET_FD) { 524 speed = NGE_10M; 525 duplex = NGE_FD; 526 } else if (anar & MII_10BASET_HD) { 527 speed = NGE_10M; 528 duplex = NGE_HD; 529 } 530 } 531 break; 532 case MII_IN: 533 anar = nge_mii_get16(ngep, MII_AN_ADVERT); 534 lpan = nge_mii_get16(ngep, MII_AN_LPABLE); 535 if (lpan != 0) 536 anar = (anar & lpan); 537 538 if (anar & MII_100BASET_FD) { 539 speed = NGE_100M; 540 duplex = NGE_FD; 541 } else if (anar & MII_100BASET_HD) { 542 speed = NGE_100M; 543 duplex = NGE_HD; 544 } else if (anar & MII_10BASET_FD) { 545 speed = NGE_10M; 546 duplex = NGE_FD; 547 } else if (anar & MII_10BASET_HD) { 548 speed = NGE_10M; 549 duplex = NGE_HD; 550 } 551 break; 552 } 553 554 555 /* 556 * We will only consider the link UP if all the readings 557 * are consistent and give meaningful results ... 558 */ 559 linkup = nge_copper_link_speed[speed] > 0; 560 linkup &= nge_copper_link_duplex[duplex] != LINK_DUPLEX_UNKNOWN; 561 linkup &= BIS(mii_status, MII_STATUS_LINKUP); 562 linkup &= BIS(mii_cs.cs_val, MII_STATUS_LINKUP); 563 564 /* 565 * Record current register values, then reread status 566 * register & loop until it stabilises ... 567 */ 568 ngep->phy_gen_status = mii_status; 569 mii_status = nge_mii_get16(ngep, MII_STATUS); 570 } while (mii_status != ngep->phy_gen_status); 571 572 /* Get the Link Partner Ability */ 573 mii_exstatus = nge_mii_get16(ngep, MII_1000BASE_T_STATUS); 574 lpan = nge_mii_get16(ngep, MII_AN_LPABLE); 575 if (mii_exstatus & MII_1000BT_STAT_LP_FDX_CAP) { 576 ngep->param_lp_autoneg = B_TRUE; 577 ngep->param_link_autoneg = B_TRUE; 578 ngep->param_lp_1000fdx = B_TRUE; 579 } 580 if (mii_exstatus & MII_1000BT_STAT_LP_HDX_CAP) { 581 ngep->param_lp_autoneg = B_TRUE; 582 ngep->param_link_autoneg = B_TRUE; 583 ngep->param_lp_1000hdx = B_TRUE; 584 } 585 if (lpan & MII_100BASET_FD) 586 ngep->param_lp_100fdx = B_TRUE; 587 if (lpan & MII_100BASET_HD) 588 ngep->param_lp_100hdx = B_TRUE; 589 if (lpan & MII_10BASET_FD) 590 ngep->param_lp_10fdx = B_TRUE; 591 if (lpan & MII_10BASET_HD) 592 ngep->param_lp_10hdx = B_TRUE; 593 if (lpan & MII_LP_ASYM_PAUSE) 594 ngep->param_lp_asym_pause = B_TRUE; 595 if (lpan & MII_LP_PAUSE) 596 ngep->param_lp_pause = B_TRUE; 597 ngep->param_link_tx_pause = B_FALSE; 598 599 if (ngep->param_adv_autoneg) 600 ngep->param_link_rx_pause = B_FALSE; 601 else 602 ngep->param_link_rx_pause = ngep->param_adv_pause; 603 if (linkup) { 604 ngep->param_link_up = linkup; 605 ngep->param_link_speed = nge_copper_link_speed[speed]; 606 ngep->param_link_duplex = nge_copper_link_duplex[duplex]; 607 } else { 608 ngep->param_link_up = B_FALSE; 609 ngep->param_link_speed = 0; 610 ngep->param_link_duplex = LINK_DUPLEX_UNKNOWN; 611 } 612 NGE_DEBUG(("nge_check_copper: link now %s speed %d duplex %d", 613 UPORDOWN(ngep->param_link_up), 614 ngep->param_link_speed, 615 ngep->param_link_duplex)); 616 617 return (B_FALSE); 618 } 619 620 /* 621 * Because the network chipset embedded in Ck8-04 bridge is only a mac chipset, 622 * the different vendor can use different media(serdes and copper). 623 * To make it easier to extend the driver to support more platforms with ck8-04, 624 * For example, one platform with serdes support, 625 * wrapper phy operation functions. 626 * But now, only supply copper phy operations. 627 */ 628 static const phys_ops_t copper_ops = { 629 nge_phy_restart, 630 nge_update_copper, 631 nge_check_copper 632 }; 633 634 /* 635 * Here we have to determine which media we're using (copper or serdes). 636 * Once that's done, we can initialise the physical layer appropriately. 637 */ 638 void 639 nge_phys_init(nge_t *ngep) 640 { 641 nge_mac2phy m2p; 642 NGE_TRACE(("nge_phys_init($%p)", (void *)ngep)); 643 644 /* Get the phy type from MAC2PHY register */ 645 m2p.m2p_val = nge_reg_get32(ngep, NGE_MAC2PHY); 646 ngep->phy_mode = m2p.m2p_bits.in_type; 647 if ((ngep->phy_mode != RGMII_IN) && (ngep->phy_mode != MII_IN)) { 648 ngep->phy_mode = RGMII_IN; 649 m2p.m2p_bits.in_type = RGMII_IN; 650 nge_reg_put32(ngep, NGE_MAC2PHY, m2p.m2p_val); 651 } 652 653 /* 654 * Probe for the type of the PHY. 655 */ 656 ngep->phy_xmii_addr = 1; 657 (void) nge_phy_probe(ngep); 658 ngep->chipinfo.flags |= CHIP_FLAG_COPPER; 659 ngep->physops = &copper_ops; 660 (*(ngep->physops->phys_restart))(ngep); 661 } 662