diff options
Diffstat (limited to 'drivers/net/e1000e/phy.c')
| -rw-r--r-- | drivers/net/e1000e/phy.c | 540 |
1 files changed, 354 insertions, 186 deletions
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 994401fd0664..85f955f70417 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c | |||
| @@ -71,7 +71,6 @@ static const u16 e1000_igp_2_cable_length_table[] = | |||
| 71 | #define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15) | 71 | #define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15) |
| 72 | #define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift 100/10 */ | 72 | #define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift 100/10 */ |
| 73 | #define I82577_CTRL_REG 23 | 73 | #define I82577_CTRL_REG 23 |
| 74 | #define I82577_CTRL_DOWNSHIFT_MASK (7 << 10) | ||
| 75 | 74 | ||
| 76 | /* 82577 specific PHY registers */ | 75 | /* 82577 specific PHY registers */ |
| 77 | #define I82577_PHY_CTRL_2 18 | 76 | #define I82577_PHY_CTRL_2 18 |
| @@ -95,13 +94,6 @@ static const u16 e1000_igp_2_cable_length_table[] = | |||
| 95 | /* BM PHY Copper Specific Control 1 */ | 94 | /* BM PHY Copper Specific Control 1 */ |
| 96 | #define BM_CS_CTRL1 16 | 95 | #define BM_CS_CTRL1 16 |
| 97 | 96 | ||
| 98 | /* BM PHY Copper Specific Status */ | ||
| 99 | #define BM_CS_STATUS 17 | ||
| 100 | #define BM_CS_STATUS_LINK_UP 0x0400 | ||
| 101 | #define BM_CS_STATUS_RESOLVED 0x0800 | ||
| 102 | #define BM_CS_STATUS_SPEED_MASK 0xC000 | ||
| 103 | #define BM_CS_STATUS_SPEED_1000 0x8000 | ||
| 104 | |||
| 105 | #define HV_MUX_DATA_CTRL PHY_REG(776, 16) | 97 | #define HV_MUX_DATA_CTRL PHY_REG(776, 16) |
| 106 | #define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 | 98 | #define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 |
| 107 | #define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 | 99 | #define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 |
| @@ -164,16 +156,25 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw) | |||
| 164 | * MDIC mode. No harm in trying again in this case since | 156 | * MDIC mode. No harm in trying again in this case since |
| 165 | * the PHY ID is unknown at this point anyway | 157 | * the PHY ID is unknown at this point anyway |
| 166 | */ | 158 | */ |
| 159 | ret_val = phy->ops.acquire_phy(hw); | ||
| 160 | if (ret_val) | ||
| 161 | goto out; | ||
| 167 | ret_val = e1000_set_mdio_slow_mode_hv(hw, true); | 162 | ret_val = e1000_set_mdio_slow_mode_hv(hw, true); |
| 168 | if (ret_val) | 163 | if (ret_val) |
| 169 | goto out; | 164 | goto out; |
| 165 | phy->ops.release_phy(hw); | ||
| 170 | 166 | ||
| 171 | retry_count++; | 167 | retry_count++; |
| 172 | } | 168 | } |
| 173 | out: | 169 | out: |
| 174 | /* Revert to MDIO fast mode, if applicable */ | 170 | /* Revert to MDIO fast mode, if applicable */ |
| 175 | if (retry_count) | 171 | if (retry_count) { |
| 172 | ret_val = phy->ops.acquire_phy(hw); | ||
| 173 | if (ret_val) | ||
| 174 | return ret_val; | ||
| 176 | ret_val = e1000_set_mdio_slow_mode_hv(hw, false); | 175 | ret_val = e1000_set_mdio_slow_mode_hv(hw, false); |
| 176 | phy->ops.release_phy(hw); | ||
| 177 | } | ||
| 177 | 178 | ||
| 178 | return ret_val; | 179 | return ret_val; |
| 179 | } | 180 | } |
| @@ -354,94 +355,173 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 354 | } | 355 | } |
| 355 | 356 | ||
| 356 | /** | 357 | /** |
| 357 | * e1000e_read_phy_reg_igp - Read igp PHY register | 358 | * __e1000e_read_phy_reg_igp - Read igp PHY register |
| 358 | * @hw: pointer to the HW structure | 359 | * @hw: pointer to the HW structure |
| 359 | * @offset: register offset to be read | 360 | * @offset: register offset to be read |
| 360 | * @data: pointer to the read data | 361 | * @data: pointer to the read data |
| 362 | * @locked: semaphore has already been acquired or not | ||
| 361 | * | 363 | * |
| 362 | * Acquires semaphore, if necessary, then reads the PHY register at offset | 364 | * Acquires semaphore, if necessary, then reads the PHY register at offset |
| 363 | * and storing the retrieved information in data. Release any acquired | 365 | * and stores the retrieved information in data. Release any acquired |
| 364 | * semaphores before exiting. | 366 | * semaphores before exiting. |
| 365 | **/ | 367 | **/ |
| 366 | s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) | 368 | static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data, |
| 369 | bool locked) | ||
| 367 | { | 370 | { |
| 368 | s32 ret_val; | 371 | s32 ret_val = 0; |
| 369 | 372 | ||
| 370 | ret_val = hw->phy.ops.acquire_phy(hw); | 373 | if (!locked) { |
| 371 | if (ret_val) | 374 | if (!(hw->phy.ops.acquire_phy)) |
| 372 | return ret_val; | 375 | goto out; |
| 376 | |||
| 377 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 378 | if (ret_val) | ||
| 379 | goto out; | ||
| 380 | } | ||
| 373 | 381 | ||
| 374 | if (offset > MAX_PHY_MULTI_PAGE_REG) { | 382 | if (offset > MAX_PHY_MULTI_PAGE_REG) { |
| 375 | ret_val = e1000e_write_phy_reg_mdic(hw, | 383 | ret_val = e1000e_write_phy_reg_mdic(hw, |
| 376 | IGP01E1000_PHY_PAGE_SELECT, | 384 | IGP01E1000_PHY_PAGE_SELECT, |
| 377 | (u16)offset); | 385 | (u16)offset); |
| 378 | if (ret_val) { | 386 | if (ret_val) |
| 379 | hw->phy.ops.release_phy(hw); | 387 | goto release; |
| 380 | return ret_val; | ||
| 381 | } | ||
| 382 | } | 388 | } |
| 383 | 389 | ||
| 384 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, | 390 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, |
| 385 | data); | 391 | data); |
| 386 | |||
| 387 | hw->phy.ops.release_phy(hw); | ||
| 388 | 392 | ||
| 393 | release: | ||
| 394 | if (!locked) | ||
| 395 | hw->phy.ops.release_phy(hw); | ||
| 396 | out: | ||
| 389 | return ret_val; | 397 | return ret_val; |
| 390 | } | 398 | } |
| 391 | 399 | ||
| 392 | /** | 400 | /** |
| 401 | * e1000e_read_phy_reg_igp - Read igp PHY register | ||
| 402 | * @hw: pointer to the HW structure | ||
| 403 | * @offset: register offset to be read | ||
| 404 | * @data: pointer to the read data | ||
| 405 | * | ||
| 406 | * Acquires semaphore then reads the PHY register at offset and stores the | ||
| 407 | * retrieved information in data. | ||
| 408 | * Release the acquired semaphore before exiting. | ||
| 409 | **/ | ||
| 410 | s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) | ||
| 411 | { | ||
| 412 | return __e1000e_read_phy_reg_igp(hw, offset, data, false); | ||
| 413 | } | ||
| 414 | |||
| 415 | /** | ||
| 416 | * e1000e_read_phy_reg_igp_locked - Read igp PHY register | ||
| 417 | * @hw: pointer to the HW structure | ||
| 418 | * @offset: register offset to be read | ||
| 419 | * @data: pointer to the read data | ||
| 420 | * | ||
| 421 | * Reads the PHY register at offset and stores the retrieved information | ||
| 422 | * in data. Assumes semaphore already acquired. | ||
| 423 | **/ | ||
| 424 | s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data) | ||
| 425 | { | ||
| 426 | return __e1000e_read_phy_reg_igp(hw, offset, data, true); | ||
| 427 | } | ||
| 428 | |||
| 429 | /** | ||
| 393 | * e1000e_write_phy_reg_igp - Write igp PHY register | 430 | * e1000e_write_phy_reg_igp - Write igp PHY register |
| 394 | * @hw: pointer to the HW structure | 431 | * @hw: pointer to the HW structure |
| 395 | * @offset: register offset to write to | 432 | * @offset: register offset to write to |
| 396 | * @data: data to write at register offset | 433 | * @data: data to write at register offset |
| 434 | * @locked: semaphore has already been acquired or not | ||
| 397 | * | 435 | * |
| 398 | * Acquires semaphore, if necessary, then writes the data to PHY register | 436 | * Acquires semaphore, if necessary, then writes the data to PHY register |
| 399 | * at the offset. Release any acquired semaphores before exiting. | 437 | * at the offset. Release any acquired semaphores before exiting. |
| 400 | **/ | 438 | **/ |
| 401 | s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) | 439 | static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data, |
| 440 | bool locked) | ||
| 402 | { | 441 | { |
| 403 | s32 ret_val; | 442 | s32 ret_val = 0; |
| 404 | 443 | ||
| 405 | ret_val = hw->phy.ops.acquire_phy(hw); | 444 | if (!locked) { |
| 406 | if (ret_val) | 445 | if (!(hw->phy.ops.acquire_phy)) |
| 407 | return ret_val; | 446 | goto out; |
| 447 | |||
| 448 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 449 | if (ret_val) | ||
| 450 | goto out; | ||
| 451 | } | ||
| 408 | 452 | ||
| 409 | if (offset > MAX_PHY_MULTI_PAGE_REG) { | 453 | if (offset > MAX_PHY_MULTI_PAGE_REG) { |
| 410 | ret_val = e1000e_write_phy_reg_mdic(hw, | 454 | ret_val = e1000e_write_phy_reg_mdic(hw, |
| 411 | IGP01E1000_PHY_PAGE_SELECT, | 455 | IGP01E1000_PHY_PAGE_SELECT, |
| 412 | (u16)offset); | 456 | (u16)offset); |
| 413 | if (ret_val) { | 457 | if (ret_val) |
| 414 | hw->phy.ops.release_phy(hw); | 458 | goto release; |
| 415 | return ret_val; | ||
| 416 | } | ||
| 417 | } | 459 | } |
| 418 | 460 | ||
| 419 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, | 461 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, |
| 420 | data); | 462 | data); |
| 421 | 463 | ||
| 422 | hw->phy.ops.release_phy(hw); | 464 | release: |
| 465 | if (!locked) | ||
| 466 | hw->phy.ops.release_phy(hw); | ||
| 423 | 467 | ||
| 468 | out: | ||
| 424 | return ret_val; | 469 | return ret_val; |
| 425 | } | 470 | } |
| 426 | 471 | ||
| 427 | /** | 472 | /** |
| 428 | * e1000e_read_kmrn_reg - Read kumeran register | 473 | * e1000e_write_phy_reg_igp - Write igp PHY register |
| 474 | * @hw: pointer to the HW structure | ||
| 475 | * @offset: register offset to write to | ||
| 476 | * @data: data to write at register offset | ||
| 477 | * | ||
| 478 | * Acquires semaphore then writes the data to PHY register | ||
| 479 | * at the offset. Release any acquired semaphores before exiting. | ||
| 480 | **/ | ||
| 481 | s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) | ||
| 482 | { | ||
| 483 | return __e1000e_write_phy_reg_igp(hw, offset, data, false); | ||
| 484 | } | ||
| 485 | |||
| 486 | /** | ||
| 487 | * e1000e_write_phy_reg_igp_locked - Write igp PHY register | ||
| 488 | * @hw: pointer to the HW structure | ||
| 489 | * @offset: register offset to write to | ||
| 490 | * @data: data to write at register offset | ||
| 491 | * | ||
| 492 | * Writes the data to PHY register at the offset. | ||
| 493 | * Assumes semaphore already acquired. | ||
| 494 | **/ | ||
| 495 | s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data) | ||
| 496 | { | ||
| 497 | return __e1000e_write_phy_reg_igp(hw, offset, data, true); | ||
| 498 | } | ||
| 499 | |||
| 500 | /** | ||
| 501 | * __e1000_read_kmrn_reg - Read kumeran register | ||
| 429 | * @hw: pointer to the HW structure | 502 | * @hw: pointer to the HW structure |
| 430 | * @offset: register offset to be read | 503 | * @offset: register offset to be read |
| 431 | * @data: pointer to the read data | 504 | * @data: pointer to the read data |
| 505 | * @locked: semaphore has already been acquired or not | ||
| 432 | * | 506 | * |
| 433 | * Acquires semaphore, if necessary. Then reads the PHY register at offset | 507 | * Acquires semaphore, if necessary. Then reads the PHY register at offset |
| 434 | * using the kumeran interface. The information retrieved is stored in data. | 508 | * using the kumeran interface. The information retrieved is stored in data. |
| 435 | * Release any acquired semaphores before exiting. | 509 | * Release any acquired semaphores before exiting. |
| 436 | **/ | 510 | **/ |
| 437 | s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) | 511 | static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, |
| 512 | bool locked) | ||
| 438 | { | 513 | { |
| 439 | u32 kmrnctrlsta; | 514 | u32 kmrnctrlsta; |
| 440 | s32 ret_val; | 515 | s32 ret_val = 0; |
| 441 | 516 | ||
| 442 | ret_val = hw->phy.ops.acquire_phy(hw); | 517 | if (!locked) { |
| 443 | if (ret_val) | 518 | if (!(hw->phy.ops.acquire_phy)) |
| 444 | return ret_val; | 519 | goto out; |
| 520 | |||
| 521 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 522 | if (ret_val) | ||
| 523 | goto out; | ||
| 524 | } | ||
| 445 | 525 | ||
| 446 | kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & | 526 | kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & |
| 447 | E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; | 527 | E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; |
| @@ -452,41 +532,111 @@ s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) | |||
| 452 | kmrnctrlsta = er32(KMRNCTRLSTA); | 532 | kmrnctrlsta = er32(KMRNCTRLSTA); |
| 453 | *data = (u16)kmrnctrlsta; | 533 | *data = (u16)kmrnctrlsta; |
| 454 | 534 | ||
| 455 | hw->phy.ops.release_phy(hw); | 535 | if (!locked) |
| 536 | hw->phy.ops.release_phy(hw); | ||
| 456 | 537 | ||
| 538 | out: | ||
| 457 | return ret_val; | 539 | return ret_val; |
| 458 | } | 540 | } |
| 459 | 541 | ||
| 460 | /** | 542 | /** |
| 461 | * e1000e_write_kmrn_reg - Write kumeran register | 543 | * e1000e_read_kmrn_reg - Read kumeran register |
| 544 | * @hw: pointer to the HW structure | ||
| 545 | * @offset: register offset to be read | ||
| 546 | * @data: pointer to the read data | ||
| 547 | * | ||
| 548 | * Acquires semaphore then reads the PHY register at offset using the | ||
| 549 | * kumeran interface. The information retrieved is stored in data. | ||
| 550 | * Release the acquired semaphore before exiting. | ||
| 551 | **/ | ||
| 552 | s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) | ||
| 553 | { | ||
| 554 | return __e1000_read_kmrn_reg(hw, offset, data, false); | ||
| 555 | } | ||
| 556 | |||
| 557 | /** | ||
| 558 | * e1000e_read_kmrn_reg_locked - Read kumeran register | ||
| 559 | * @hw: pointer to the HW structure | ||
| 560 | * @offset: register offset to be read | ||
| 561 | * @data: pointer to the read data | ||
| 562 | * | ||
| 563 | * Reads the PHY register at offset using the kumeran interface. The | ||
| 564 | * information retrieved is stored in data. | ||
| 565 | * Assumes semaphore already acquired. | ||
| 566 | **/ | ||
| 567 | s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) | ||
| 568 | { | ||
| 569 | return __e1000_read_kmrn_reg(hw, offset, data, true); | ||
| 570 | } | ||
| 571 | |||
| 572 | /** | ||
| 573 | * __e1000_write_kmrn_reg - Write kumeran register | ||
| 462 | * @hw: pointer to the HW structure | 574 | * @hw: pointer to the HW structure |
| 463 | * @offset: register offset to write to | 575 | * @offset: register offset to write to |
| 464 | * @data: data to write at register offset | 576 | * @data: data to write at register offset |
| 577 | * @locked: semaphore has already been acquired or not | ||
| 465 | * | 578 | * |
| 466 | * Acquires semaphore, if necessary. Then write the data to PHY register | 579 | * Acquires semaphore, if necessary. Then write the data to PHY register |
| 467 | * at the offset using the kumeran interface. Release any acquired semaphores | 580 | * at the offset using the kumeran interface. Release any acquired semaphores |
| 468 | * before exiting. | 581 | * before exiting. |
| 469 | **/ | 582 | **/ |
| 470 | s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) | 583 | static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, |
| 584 | bool locked) | ||
| 471 | { | 585 | { |
| 472 | u32 kmrnctrlsta; | 586 | u32 kmrnctrlsta; |
| 473 | s32 ret_val; | 587 | s32 ret_val = 0; |
| 474 | 588 | ||
| 475 | ret_val = hw->phy.ops.acquire_phy(hw); | 589 | if (!locked) { |
| 476 | if (ret_val) | 590 | if (!(hw->phy.ops.acquire_phy)) |
| 477 | return ret_val; | 591 | goto out; |
| 592 | |||
| 593 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 594 | if (ret_val) | ||
| 595 | goto out; | ||
| 596 | } | ||
| 478 | 597 | ||
| 479 | kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & | 598 | kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & |
| 480 | E1000_KMRNCTRLSTA_OFFSET) | data; | 599 | E1000_KMRNCTRLSTA_OFFSET) | data; |
| 481 | ew32(KMRNCTRLSTA, kmrnctrlsta); | 600 | ew32(KMRNCTRLSTA, kmrnctrlsta); |
| 482 | 601 | ||
| 483 | udelay(2); | 602 | udelay(2); |
| 484 | hw->phy.ops.release_phy(hw); | ||
| 485 | 603 | ||
| 604 | if (!locked) | ||
| 605 | hw->phy.ops.release_phy(hw); | ||
| 606 | |||
| 607 | out: | ||
| 486 | return ret_val; | 608 | return ret_val; |
| 487 | } | 609 | } |
| 488 | 610 | ||
| 489 | /** | 611 | /** |
| 612 | * e1000e_write_kmrn_reg - Write kumeran register | ||
| 613 | * @hw: pointer to the HW structure | ||
| 614 | * @offset: register offset to write to | ||
| 615 | * @data: data to write at register offset | ||
| 616 | * | ||
| 617 | * Acquires semaphore then writes the data to the PHY register at the offset | ||
| 618 | * using the kumeran interface. Release the acquired semaphore before exiting. | ||
| 619 | **/ | ||
| 620 | s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) | ||
| 621 | { | ||
| 622 | return __e1000_write_kmrn_reg(hw, offset, data, false); | ||
| 623 | } | ||
| 624 | |||
| 625 | /** | ||
| 626 | * e1000e_write_kmrn_reg_locked - Write kumeran register | ||
| 627 | * @hw: pointer to the HW structure | ||
| 628 | * @offset: register offset to write to | ||
| 629 | * @data: data to write at register offset | ||
| 630 | * | ||
| 631 | * Write the data to PHY register at the offset using the kumeran interface. | ||
| 632 | * Assumes semaphore already acquired. | ||
| 633 | **/ | ||
| 634 | s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) | ||
| 635 | { | ||
| 636 | return __e1000_write_kmrn_reg(hw, offset, data, true); | ||
| 637 | } | ||
| 638 | |||
| 639 | /** | ||
| 490 | * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link | 640 | * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link |
| 491 | * @hw: pointer to the HW structure | 641 | * @hw: pointer to the HW structure |
| 492 | * | 642 | * |
| @@ -509,15 +659,6 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) | |||
| 509 | phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; | 659 | phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; |
| 510 | 660 | ||
| 511 | ret_val = phy->ops.write_phy_reg(hw, I82577_CFG_REG, phy_data); | 661 | ret_val = phy->ops.write_phy_reg(hw, I82577_CFG_REG, phy_data); |
| 512 | if (ret_val) | ||
| 513 | goto out; | ||
| 514 | |||
| 515 | /* Set number of link attempts before downshift */ | ||
| 516 | ret_val = phy->ops.read_phy_reg(hw, I82577_CTRL_REG, &phy_data); | ||
| 517 | if (ret_val) | ||
| 518 | goto out; | ||
| 519 | phy_data &= ~I82577_CTRL_DOWNSHIFT_MASK; | ||
| 520 | ret_val = phy->ops.write_phy_reg(hw, I82577_CTRL_REG, phy_data); | ||
| 521 | 662 | ||
| 522 | out: | 663 | out: |
| 523 | return ret_val; | 664 | return ret_val; |
| @@ -2105,6 +2246,10 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 2105 | u32 page = offset >> IGP_PAGE_SHIFT; | 2246 | u32 page = offset >> IGP_PAGE_SHIFT; |
| 2106 | u32 page_shift = 0; | 2247 | u32 page_shift = 0; |
| 2107 | 2248 | ||
| 2249 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2250 | if (ret_val) | ||
| 2251 | return ret_val; | ||
| 2252 | |||
| 2108 | /* Page 800 works differently than the rest so it has its own func */ | 2253 | /* Page 800 works differently than the rest so it has its own func */ |
| 2109 | if (page == BM_WUC_PAGE) { | 2254 | if (page == BM_WUC_PAGE) { |
| 2110 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, | 2255 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, |
| @@ -2112,10 +2257,6 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 2112 | goto out; | 2257 | goto out; |
| 2113 | } | 2258 | } |
| 2114 | 2259 | ||
| 2115 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2116 | if (ret_val) | ||
| 2117 | goto out; | ||
| 2118 | |||
| 2119 | hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); | 2260 | hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); |
| 2120 | 2261 | ||
| 2121 | if (offset > MAX_PHY_MULTI_PAGE_REG) { | 2262 | if (offset > MAX_PHY_MULTI_PAGE_REG) { |
| @@ -2135,18 +2276,15 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 2135 | /* Page is shifted left, PHY expects (page x 32) */ | 2276 | /* Page is shifted left, PHY expects (page x 32) */ |
| 2136 | ret_val = e1000e_write_phy_reg_mdic(hw, page_select, | 2277 | ret_val = e1000e_write_phy_reg_mdic(hw, page_select, |
| 2137 | (page << page_shift)); | 2278 | (page << page_shift)); |
| 2138 | if (ret_val) { | 2279 | if (ret_val) |
| 2139 | hw->phy.ops.release_phy(hw); | ||
| 2140 | goto out; | 2280 | goto out; |
| 2141 | } | ||
| 2142 | } | 2281 | } |
| 2143 | 2282 | ||
| 2144 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, | 2283 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, |
| 2145 | data); | 2284 | data); |
| 2146 | 2285 | ||
| 2147 | hw->phy.ops.release_phy(hw); | ||
| 2148 | |||
| 2149 | out: | 2286 | out: |
| 2287 | hw->phy.ops.release_phy(hw); | ||
| 2150 | return ret_val; | 2288 | return ret_val; |
| 2151 | } | 2289 | } |
| 2152 | 2290 | ||
| @@ -2167,6 +2305,10 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) | |||
| 2167 | u32 page = offset >> IGP_PAGE_SHIFT; | 2305 | u32 page = offset >> IGP_PAGE_SHIFT; |
| 2168 | u32 page_shift = 0; | 2306 | u32 page_shift = 0; |
| 2169 | 2307 | ||
| 2308 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2309 | if (ret_val) | ||
| 2310 | return ret_val; | ||
| 2311 | |||
| 2170 | /* Page 800 works differently than the rest so it has its own func */ | 2312 | /* Page 800 works differently than the rest so it has its own func */ |
| 2171 | if (page == BM_WUC_PAGE) { | 2313 | if (page == BM_WUC_PAGE) { |
| 2172 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, | 2314 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, |
| @@ -2174,10 +2316,6 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) | |||
| 2174 | goto out; | 2316 | goto out; |
| 2175 | } | 2317 | } |
| 2176 | 2318 | ||
| 2177 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2178 | if (ret_val) | ||
| 2179 | goto out; | ||
| 2180 | |||
| 2181 | hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); | 2319 | hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); |
| 2182 | 2320 | ||
| 2183 | if (offset > MAX_PHY_MULTI_PAGE_REG) { | 2321 | if (offset > MAX_PHY_MULTI_PAGE_REG) { |
| @@ -2197,17 +2335,14 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) | |||
| 2197 | /* Page is shifted left, PHY expects (page x 32) */ | 2335 | /* Page is shifted left, PHY expects (page x 32) */ |
| 2198 | ret_val = e1000e_write_phy_reg_mdic(hw, page_select, | 2336 | ret_val = e1000e_write_phy_reg_mdic(hw, page_select, |
| 2199 | (page << page_shift)); | 2337 | (page << page_shift)); |
| 2200 | if (ret_val) { | 2338 | if (ret_val) |
| 2201 | hw->phy.ops.release_phy(hw); | ||
| 2202 | goto out; | 2339 | goto out; |
| 2203 | } | ||
| 2204 | } | 2340 | } |
| 2205 | 2341 | ||
| 2206 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, | 2342 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, |
| 2207 | data); | 2343 | data); |
| 2208 | hw->phy.ops.release_phy(hw); | ||
| 2209 | |||
| 2210 | out: | 2344 | out: |
| 2345 | hw->phy.ops.release_phy(hw); | ||
| 2211 | return ret_val; | 2346 | return ret_val; |
| 2212 | } | 2347 | } |
| 2213 | 2348 | ||
| @@ -2226,17 +2361,17 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) | |||
| 2226 | s32 ret_val; | 2361 | s32 ret_val; |
| 2227 | u16 page = (u16)(offset >> IGP_PAGE_SHIFT); | 2362 | u16 page = (u16)(offset >> IGP_PAGE_SHIFT); |
| 2228 | 2363 | ||
| 2364 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2365 | if (ret_val) | ||
| 2366 | return ret_val; | ||
| 2367 | |||
| 2229 | /* Page 800 works differently than the rest so it has its own func */ | 2368 | /* Page 800 works differently than the rest so it has its own func */ |
| 2230 | if (page == BM_WUC_PAGE) { | 2369 | if (page == BM_WUC_PAGE) { |
| 2231 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, | 2370 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, |
| 2232 | true); | 2371 | true); |
| 2233 | return ret_val; | 2372 | goto out; |
| 2234 | } | 2373 | } |
| 2235 | 2374 | ||
| 2236 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2237 | if (ret_val) | ||
| 2238 | return ret_val; | ||
| 2239 | |||
| 2240 | hw->phy.addr = 1; | 2375 | hw->phy.addr = 1; |
| 2241 | 2376 | ||
| 2242 | if (offset > MAX_PHY_MULTI_PAGE_REG) { | 2377 | if (offset > MAX_PHY_MULTI_PAGE_REG) { |
| @@ -2245,16 +2380,14 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) | |||
| 2245 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, | 2380 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, |
| 2246 | page); | 2381 | page); |
| 2247 | 2382 | ||
| 2248 | if (ret_val) { | 2383 | if (ret_val) |
| 2249 | hw->phy.ops.release_phy(hw); | 2384 | goto out; |
| 2250 | return ret_val; | ||
| 2251 | } | ||
| 2252 | } | 2385 | } |
| 2253 | 2386 | ||
| 2254 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, | 2387 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, |
| 2255 | data); | 2388 | data); |
| 2389 | out: | ||
| 2256 | hw->phy.ops.release_phy(hw); | 2390 | hw->phy.ops.release_phy(hw); |
| 2257 | |||
| 2258 | return ret_val; | 2391 | return ret_val; |
| 2259 | } | 2392 | } |
| 2260 | 2393 | ||
| @@ -2272,17 +2405,17 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 2272 | s32 ret_val; | 2405 | s32 ret_val; |
| 2273 | u16 page = (u16)(offset >> IGP_PAGE_SHIFT); | 2406 | u16 page = (u16)(offset >> IGP_PAGE_SHIFT); |
| 2274 | 2407 | ||
| 2408 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2409 | if (ret_val) | ||
| 2410 | return ret_val; | ||
| 2411 | |||
| 2275 | /* Page 800 works differently than the rest so it has its own func */ | 2412 | /* Page 800 works differently than the rest so it has its own func */ |
| 2276 | if (page == BM_WUC_PAGE) { | 2413 | if (page == BM_WUC_PAGE) { |
| 2277 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, | 2414 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, |
| 2278 | false); | 2415 | false); |
| 2279 | return ret_val; | 2416 | goto out; |
| 2280 | } | 2417 | } |
| 2281 | 2418 | ||
| 2282 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2283 | if (ret_val) | ||
| 2284 | return ret_val; | ||
| 2285 | |||
| 2286 | hw->phy.addr = 1; | 2419 | hw->phy.addr = 1; |
| 2287 | 2420 | ||
| 2288 | if (offset > MAX_PHY_MULTI_PAGE_REG) { | 2421 | if (offset > MAX_PHY_MULTI_PAGE_REG) { |
| @@ -2290,17 +2423,15 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 2290 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, | 2423 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, |
| 2291 | page); | 2424 | page); |
| 2292 | 2425 | ||
| 2293 | if (ret_val) { | 2426 | if (ret_val) |
| 2294 | hw->phy.ops.release_phy(hw); | 2427 | goto out; |
| 2295 | return ret_val; | ||
| 2296 | } | ||
| 2297 | } | 2428 | } |
| 2298 | 2429 | ||
| 2299 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, | 2430 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, |
| 2300 | data); | 2431 | data); |
| 2301 | 2432 | ||
| 2433 | out: | ||
| 2302 | hw->phy.ops.release_phy(hw); | 2434 | hw->phy.ops.release_phy(hw); |
| 2303 | |||
| 2304 | return ret_val; | 2435 | return ret_val; |
| 2305 | } | 2436 | } |
| 2306 | 2437 | ||
| @@ -2320,6 +2451,8 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 2320 | * 3) Write the address using the address opcode (0x11) | 2451 | * 3) Write the address using the address opcode (0x11) |
| 2321 | * 4) Read or write the data using the data opcode (0x12) | 2452 | * 4) Read or write the data using the data opcode (0x12) |
| 2322 | * 5) Restore 769_17.2 to its original value | 2453 | * 5) Restore 769_17.2 to its original value |
| 2454 | * | ||
| 2455 | * Assumes semaphore already acquired. | ||
| 2323 | **/ | 2456 | **/ |
| 2324 | static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, | 2457 | static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, |
| 2325 | u16 *data, bool read) | 2458 | u16 *data, bool read) |
| @@ -2327,20 +2460,12 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, | |||
| 2327 | s32 ret_val; | 2460 | s32 ret_val; |
| 2328 | u16 reg = BM_PHY_REG_NUM(offset); | 2461 | u16 reg = BM_PHY_REG_NUM(offset); |
| 2329 | u16 phy_reg = 0; | 2462 | u16 phy_reg = 0; |
| 2330 | u8 phy_acquired = 1; | ||
| 2331 | |||
| 2332 | 2463 | ||
| 2333 | /* Gig must be disabled for MDIO accesses to page 800 */ | 2464 | /* Gig must be disabled for MDIO accesses to page 800 */ |
| 2334 | if ((hw->mac.type == e1000_pchlan) && | 2465 | if ((hw->mac.type == e1000_pchlan) && |
| 2335 | (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) | 2466 | (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) |
| 2336 | hw_dbg(hw, "Attempting to access page 800 while gig enabled\n"); | 2467 | hw_dbg(hw, "Attempting to access page 800 while gig enabled\n"); |
| 2337 | 2468 | ||
| 2338 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2339 | if (ret_val) { | ||
| 2340 | phy_acquired = 0; | ||
| 2341 | goto out; | ||
| 2342 | } | ||
| 2343 | |||
| 2344 | /* All operations in this function are phy address 1 */ | 2469 | /* All operations in this function are phy address 1 */ |
| 2345 | hw->phy.addr = 1; | 2470 | hw->phy.addr = 1; |
| 2346 | 2471 | ||
| @@ -2397,8 +2522,6 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, | |||
| 2397 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); | 2522 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); |
| 2398 | 2523 | ||
| 2399 | out: | 2524 | out: |
| 2400 | if (phy_acquired == 1) | ||
| 2401 | hw->phy.ops.release_phy(hw); | ||
| 2402 | return ret_val; | 2525 | return ret_val; |
| 2403 | } | 2526 | } |
| 2404 | 2527 | ||
| @@ -2439,52 +2562,63 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) | |||
| 2439 | return 0; | 2562 | return 0; |
| 2440 | } | 2563 | } |
| 2441 | 2564 | ||
| 2565 | /** | ||
| 2566 | * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode | ||
| 2567 | * @hw: pointer to the HW structure | ||
| 2568 | * @slow: true for slow mode, false for normal mode | ||
| 2569 | * | ||
| 2570 | * Assumes semaphore already acquired. | ||
| 2571 | **/ | ||
| 2442 | s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow) | 2572 | s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow) |
| 2443 | { | 2573 | { |
| 2444 | s32 ret_val = 0; | 2574 | s32 ret_val = 0; |
| 2445 | u16 data = 0; | 2575 | u16 data = 0; |
| 2446 | 2576 | ||
| 2447 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2448 | if (ret_val) | ||
| 2449 | return ret_val; | ||
| 2450 | |||
| 2451 | /* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */ | 2577 | /* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */ |
| 2452 | hw->phy.addr = 1; | 2578 | hw->phy.addr = 1; |
| 2453 | ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, | 2579 | ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, |
| 2454 | (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); | 2580 | (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); |
| 2455 | if (ret_val) { | 2581 | if (ret_val) |
| 2456 | hw->phy.ops.release_phy(hw); | 2582 | goto out; |
| 2457 | return ret_val; | 2583 | |
| 2458 | } | ||
| 2459 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1, | 2584 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1, |
| 2460 | (0x2180 | (slow << 10))); | 2585 | (0x2180 | (slow << 10))); |
| 2586 | if (ret_val) | ||
| 2587 | goto out; | ||
| 2461 | 2588 | ||
| 2462 | /* dummy read when reverting to fast mode - throw away result */ | 2589 | /* dummy read when reverting to fast mode - throw away result */ |
| 2463 | if (!slow) | 2590 | if (!slow) |
| 2464 | e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data); | 2591 | ret_val = e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data); |
| 2465 | |||
| 2466 | hw->phy.ops.release_phy(hw); | ||
| 2467 | 2592 | ||
| 2593 | out: | ||
| 2468 | return ret_val; | 2594 | return ret_val; |
| 2469 | } | 2595 | } |
| 2470 | 2596 | ||
| 2471 | /** | 2597 | /** |
| 2472 | * e1000_read_phy_reg_hv - Read HV PHY register | 2598 | * __e1000_read_phy_reg_hv - Read HV PHY register |
| 2473 | * @hw: pointer to the HW structure | 2599 | * @hw: pointer to the HW structure |
| 2474 | * @offset: register offset to be read | 2600 | * @offset: register offset to be read |
| 2475 | * @data: pointer to the read data | 2601 | * @data: pointer to the read data |
| 2602 | * @locked: semaphore has already been acquired or not | ||
| 2476 | * | 2603 | * |
| 2477 | * Acquires semaphore, if necessary, then reads the PHY register at offset | 2604 | * Acquires semaphore, if necessary, then reads the PHY register at offset |
| 2478 | * and storing the retrieved information in data. Release any acquired | 2605 | * and stores the retrieved information in data. Release any acquired |
| 2479 | * semaphore before exiting. | 2606 | * semaphore before exiting. |
| 2480 | **/ | 2607 | **/ |
| 2481 | s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) | 2608 | static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, |
| 2609 | bool locked) | ||
| 2482 | { | 2610 | { |
| 2483 | s32 ret_val; | 2611 | s32 ret_val; |
| 2484 | u16 page = BM_PHY_REG_PAGE(offset); | 2612 | u16 page = BM_PHY_REG_PAGE(offset); |
| 2485 | u16 reg = BM_PHY_REG_NUM(offset); | 2613 | u16 reg = BM_PHY_REG_NUM(offset); |
| 2486 | bool in_slow_mode = false; | 2614 | bool in_slow_mode = false; |
| 2487 | 2615 | ||
| 2616 | if (!locked) { | ||
| 2617 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2618 | if (ret_val) | ||
| 2619 | return ret_val; | ||
| 2620 | } | ||
| 2621 | |||
| 2488 | /* Workaround failure in MDIO access while cable is disconnected */ | 2622 | /* Workaround failure in MDIO access while cable is disconnected */ |
| 2489 | if ((hw->phy.type == e1000_phy_82577) && | 2623 | if ((hw->phy.type == e1000_phy_82577) && |
| 2490 | !(er32(STATUS) & E1000_STATUS_LU)) { | 2624 | !(er32(STATUS) & E1000_STATUS_LU)) { |
| @@ -2508,63 +2642,92 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) | |||
| 2508 | goto out; | 2642 | goto out; |
| 2509 | } | 2643 | } |
| 2510 | 2644 | ||
| 2511 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2512 | if (ret_val) | ||
| 2513 | goto out; | ||
| 2514 | |||
| 2515 | hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); | 2645 | hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); |
| 2516 | 2646 | ||
| 2517 | if (page == HV_INTC_FC_PAGE_START) | 2647 | if (page == HV_INTC_FC_PAGE_START) |
| 2518 | page = 0; | 2648 | page = 0; |
| 2519 | 2649 | ||
| 2520 | if (reg > MAX_PHY_MULTI_PAGE_REG) { | 2650 | if (reg > MAX_PHY_MULTI_PAGE_REG) { |
| 2521 | if ((hw->phy.type != e1000_phy_82578) || | 2651 | u32 phy_addr = hw->phy.addr; |
| 2522 | ((reg != I82578_ADDR_REG) && | 2652 | |
| 2523 | (reg != I82578_ADDR_REG + 1))) { | 2653 | hw->phy.addr = 1; |
| 2524 | u32 phy_addr = hw->phy.addr; | 2654 | |
| 2525 | 2655 | /* Page is shifted left, PHY expects (page x 32) */ | |
| 2526 | hw->phy.addr = 1; | 2656 | ret_val = e1000e_write_phy_reg_mdic(hw, |
| 2527 | 2657 | IGP01E1000_PHY_PAGE_SELECT, | |
| 2528 | /* Page is shifted left, PHY expects (page x 32) */ | 2658 | (page << IGP_PAGE_SHIFT)); |
| 2529 | ret_val = e1000e_write_phy_reg_mdic(hw, | 2659 | hw->phy.addr = phy_addr; |
| 2530 | IGP01E1000_PHY_PAGE_SELECT, | 2660 | |
| 2531 | (page << IGP_PAGE_SHIFT)); | 2661 | if (ret_val) |
| 2532 | if (ret_val) { | 2662 | goto out; |
| 2533 | hw->phy.ops.release_phy(hw); | ||
| 2534 | goto out; | ||
| 2535 | } | ||
| 2536 | hw->phy.addr = phy_addr; | ||
| 2537 | } | ||
| 2538 | } | 2663 | } |
| 2539 | 2664 | ||
| 2540 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, | 2665 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, |
| 2541 | data); | 2666 | data); |
| 2542 | hw->phy.ops.release_phy(hw); | ||
| 2543 | |||
| 2544 | out: | 2667 | out: |
| 2545 | /* Revert to MDIO fast mode, if applicable */ | 2668 | /* Revert to MDIO fast mode, if applicable */ |
| 2546 | if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) | 2669 | if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) |
| 2547 | ret_val = e1000_set_mdio_slow_mode_hv(hw, false); | 2670 | ret_val |= e1000_set_mdio_slow_mode_hv(hw, false); |
| 2671 | |||
| 2672 | if (!locked) | ||
| 2673 | hw->phy.ops.release_phy(hw); | ||
| 2548 | 2674 | ||
| 2549 | return ret_val; | 2675 | return ret_val; |
| 2550 | } | 2676 | } |
| 2551 | 2677 | ||
| 2552 | /** | 2678 | /** |
| 2553 | * e1000_write_phy_reg_hv - Write HV PHY register | 2679 | * e1000_read_phy_reg_hv - Read HV PHY register |
| 2680 | * @hw: pointer to the HW structure | ||
| 2681 | * @offset: register offset to be read | ||
| 2682 | * @data: pointer to the read data | ||
| 2683 | * | ||
| 2684 | * Acquires semaphore then reads the PHY register at offset and stores | ||
| 2685 | * the retrieved information in data. Release the acquired semaphore | ||
| 2686 | * before exiting. | ||
| 2687 | **/ | ||
| 2688 | s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) | ||
| 2689 | { | ||
| 2690 | return __e1000_read_phy_reg_hv(hw, offset, data, false); | ||
| 2691 | } | ||
| 2692 | |||
| 2693 | /** | ||
| 2694 | * e1000_read_phy_reg_hv_locked - Read HV PHY register | ||
| 2695 | * @hw: pointer to the HW structure | ||
| 2696 | * @offset: register offset to be read | ||
| 2697 | * @data: pointer to the read data | ||
| 2698 | * | ||
| 2699 | * Reads the PHY register at offset and stores the retrieved information | ||
| 2700 | * in data. Assumes semaphore already acquired. | ||
| 2701 | **/ | ||
| 2702 | s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data) | ||
| 2703 | { | ||
| 2704 | return __e1000_read_phy_reg_hv(hw, offset, data, true); | ||
| 2705 | } | ||
| 2706 | |||
| 2707 | /** | ||
| 2708 | * __e1000_write_phy_reg_hv - Write HV PHY register | ||
| 2554 | * @hw: pointer to the HW structure | 2709 | * @hw: pointer to the HW structure |
| 2555 | * @offset: register offset to write to | 2710 | * @offset: register offset to write to |
| 2556 | * @data: data to write at register offset | 2711 | * @data: data to write at register offset |
| 2712 | * @locked: semaphore has already been acquired or not | ||
| 2557 | * | 2713 | * |
| 2558 | * Acquires semaphore, if necessary, then writes the data to PHY register | 2714 | * Acquires semaphore, if necessary, then writes the data to PHY register |
| 2559 | * at the offset. Release any acquired semaphores before exiting. | 2715 | * at the offset. Release any acquired semaphores before exiting. |
| 2560 | **/ | 2716 | **/ |
| 2561 | s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) | 2717 | static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, |
| 2718 | bool locked) | ||
| 2562 | { | 2719 | { |
| 2563 | s32 ret_val; | 2720 | s32 ret_val; |
| 2564 | u16 page = BM_PHY_REG_PAGE(offset); | 2721 | u16 page = BM_PHY_REG_PAGE(offset); |
| 2565 | u16 reg = BM_PHY_REG_NUM(offset); | 2722 | u16 reg = BM_PHY_REG_NUM(offset); |
| 2566 | bool in_slow_mode = false; | 2723 | bool in_slow_mode = false; |
| 2567 | 2724 | ||
| 2725 | if (!locked) { | ||
| 2726 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2727 | if (ret_val) | ||
| 2728 | return ret_val; | ||
| 2729 | } | ||
| 2730 | |||
| 2568 | /* Workaround failure in MDIO access while cable is disconnected */ | 2731 | /* Workaround failure in MDIO access while cable is disconnected */ |
| 2569 | if ((hw->phy.type == e1000_phy_82577) && | 2732 | if ((hw->phy.type == e1000_phy_82577) && |
| 2570 | !(er32(STATUS) & E1000_STATUS_LU)) { | 2733 | !(er32(STATUS) & E1000_STATUS_LU)) { |
| @@ -2588,10 +2751,6 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 2588 | goto out; | 2751 | goto out; |
| 2589 | } | 2752 | } |
| 2590 | 2753 | ||
| 2591 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2592 | if (ret_val) | ||
| 2593 | goto out; | ||
| 2594 | |||
| 2595 | hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); | 2754 | hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); |
| 2596 | 2755 | ||
| 2597 | if (page == HV_INTC_FC_PAGE_START) | 2756 | if (page == HV_INTC_FC_PAGE_START) |
| @@ -2607,50 +2766,70 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 2607 | ((MAX_PHY_REG_ADDRESS & reg) == 0) && | 2766 | ((MAX_PHY_REG_ADDRESS & reg) == 0) && |
| 2608 | (data & (1 << 11))) { | 2767 | (data & (1 << 11))) { |
| 2609 | u16 data2 = 0x7EFF; | 2768 | u16 data2 = 0x7EFF; |
| 2610 | hw->phy.ops.release_phy(hw); | ||
| 2611 | ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3, | 2769 | ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3, |
| 2612 | &data2, false); | 2770 | &data2, false); |
| 2613 | if (ret_val) | 2771 | if (ret_val) |
| 2614 | goto out; | 2772 | goto out; |
| 2615 | |||
| 2616 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2617 | if (ret_val) | ||
| 2618 | goto out; | ||
| 2619 | } | 2773 | } |
| 2620 | 2774 | ||
| 2621 | if (reg > MAX_PHY_MULTI_PAGE_REG) { | 2775 | if (reg > MAX_PHY_MULTI_PAGE_REG) { |
| 2622 | if ((hw->phy.type != e1000_phy_82578) || | 2776 | u32 phy_addr = hw->phy.addr; |
| 2623 | ((reg != I82578_ADDR_REG) && | 2777 | |
| 2624 | (reg != I82578_ADDR_REG + 1))) { | 2778 | hw->phy.addr = 1; |
| 2625 | u32 phy_addr = hw->phy.addr; | 2779 | |
| 2626 | 2780 | /* Page is shifted left, PHY expects (page x 32) */ | |
| 2627 | hw->phy.addr = 1; | 2781 | ret_val = e1000e_write_phy_reg_mdic(hw, |
| 2628 | 2782 | IGP01E1000_PHY_PAGE_SELECT, | |
| 2629 | /* Page is shifted left, PHY expects (page x 32) */ | 2783 | (page << IGP_PAGE_SHIFT)); |
| 2630 | ret_val = e1000e_write_phy_reg_mdic(hw, | 2784 | hw->phy.addr = phy_addr; |
| 2631 | IGP01E1000_PHY_PAGE_SELECT, | 2785 | |
| 2632 | (page << IGP_PAGE_SHIFT)); | 2786 | if (ret_val) |
| 2633 | if (ret_val) { | 2787 | goto out; |
| 2634 | hw->phy.ops.release_phy(hw); | ||
| 2635 | goto out; | ||
| 2636 | } | ||
| 2637 | hw->phy.addr = phy_addr; | ||
| 2638 | } | ||
| 2639 | } | 2788 | } |
| 2640 | 2789 | ||
| 2641 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, | 2790 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, |
| 2642 | data); | 2791 | data); |
| 2643 | hw->phy.ops.release_phy(hw); | ||
| 2644 | 2792 | ||
| 2645 | out: | 2793 | out: |
| 2646 | /* Revert to MDIO fast mode, if applicable */ | 2794 | /* Revert to MDIO fast mode, if applicable */ |
| 2647 | if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) | 2795 | if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) |
| 2648 | ret_val = e1000_set_mdio_slow_mode_hv(hw, false); | 2796 | ret_val |= e1000_set_mdio_slow_mode_hv(hw, false); |
| 2797 | |||
| 2798 | if (!locked) | ||
| 2799 | hw->phy.ops.release_phy(hw); | ||
| 2649 | 2800 | ||
| 2650 | return ret_val; | 2801 | return ret_val; |
| 2651 | } | 2802 | } |
| 2652 | 2803 | ||
| 2653 | /** | 2804 | /** |
| 2805 | * e1000_write_phy_reg_hv - Write HV PHY register | ||
| 2806 | * @hw: pointer to the HW structure | ||
| 2807 | * @offset: register offset to write to | ||
| 2808 | * @data: data to write at register offset | ||
| 2809 | * | ||
| 2810 | * Acquires semaphore then writes the data to PHY register at the offset. | ||
| 2811 | * Release the acquired semaphores before exiting. | ||
| 2812 | **/ | ||
| 2813 | s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) | ||
| 2814 | { | ||
| 2815 | return __e1000_write_phy_reg_hv(hw, offset, data, false); | ||
| 2816 | } | ||
| 2817 | |||
| 2818 | /** | ||
| 2819 | * e1000_write_phy_reg_hv_locked - Write HV PHY register | ||
| 2820 | * @hw: pointer to the HW structure | ||
| 2821 | * @offset: register offset to write to | ||
| 2822 | * @data: data to write at register offset | ||
| 2823 | * | ||
| 2824 | * Writes the data to PHY register at the offset. Assumes semaphore | ||
| 2825 | * already acquired. | ||
| 2826 | **/ | ||
| 2827 | s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data) | ||
| 2828 | { | ||
| 2829 | return __e1000_write_phy_reg_hv(hw, offset, data, true); | ||
| 2830 | } | ||
| 2831 | |||
| 2832 | /** | ||
| 2654 | * e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page | 2833 | * e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page |
| 2655 | * @page: page to be accessed | 2834 | * @page: page to be accessed |
| 2656 | **/ | 2835 | **/ |
| @@ -2671,10 +2850,9 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page) | |||
| 2671 | * @data: pointer to the data to be read or written | 2850 | * @data: pointer to the data to be read or written |
| 2672 | * @read: determines if operation is read or written | 2851 | * @read: determines if operation is read or written |
| 2673 | * | 2852 | * |
| 2674 | * Acquires semaphore, if necessary, then reads the PHY register at offset | 2853 | * Reads the PHY register at offset and stores the retreived information |
| 2675 | * and storing the retreived information in data. Release any acquired | 2854 | * in data. Assumes semaphore already acquired. Note that the procedure |
| 2676 | * semaphores before exiting. Note that the procedure to read these regs | 2855 | * to read these regs uses the address port and data port to read/write. |
| 2677 | * uses the address port and data port to read/write. | ||
| 2678 | **/ | 2856 | **/ |
| 2679 | static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, | 2857 | static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, |
| 2680 | u16 *data, bool read) | 2858 | u16 *data, bool read) |
| @@ -2682,20 +2860,12 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, | |||
| 2682 | s32 ret_val; | 2860 | s32 ret_val; |
| 2683 | u32 addr_reg = 0; | 2861 | u32 addr_reg = 0; |
| 2684 | u32 data_reg = 0; | 2862 | u32 data_reg = 0; |
| 2685 | u8 phy_acquired = 1; | ||
| 2686 | 2863 | ||
| 2687 | /* This takes care of the difference with desktop vs mobile phy */ | 2864 | /* This takes care of the difference with desktop vs mobile phy */ |
| 2688 | addr_reg = (hw->phy.type == e1000_phy_82578) ? | 2865 | addr_reg = (hw->phy.type == e1000_phy_82578) ? |
| 2689 | I82578_ADDR_REG : I82577_ADDR_REG; | 2866 | I82578_ADDR_REG : I82577_ADDR_REG; |
| 2690 | data_reg = addr_reg + 1; | 2867 | data_reg = addr_reg + 1; |
| 2691 | 2868 | ||
| 2692 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
| 2693 | if (ret_val) { | ||
| 2694 | hw_dbg(hw, "Could not acquire PHY\n"); | ||
| 2695 | phy_acquired = 0; | ||
| 2696 | goto out; | ||
| 2697 | } | ||
| 2698 | |||
| 2699 | /* All operations in this function are phy address 2 */ | 2869 | /* All operations in this function are phy address 2 */ |
| 2700 | hw->phy.addr = 2; | 2870 | hw->phy.addr = 2; |
| 2701 | 2871 | ||
| @@ -2718,8 +2888,6 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, | |||
| 2718 | } | 2888 | } |
| 2719 | 2889 | ||
| 2720 | out: | 2890 | out: |
| 2721 | if (phy_acquired == 1) | ||
| 2722 | hw->phy.ops.release_phy(hw); | ||
| 2723 | return ret_val; | 2891 | return ret_val; |
| 2724 | } | 2892 | } |
| 2725 | 2893 | ||
