diff options
author | Bruce Allan <bruce.w.allan@intel.com> | 2011-05-13 03:20:09 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-06-09 23:33:36 -0400 |
commit | 2b6b168d52aa044363647cfff8bda5cef8068ca3 (patch) | |
tree | 8553b5c181e56e457695163fcdf5469cd9f46e39 /drivers/net/e1000e/phy.c | |
parent | 400484fa65ead1bbc3e86ea79e7505182a31bce1 (diff) |
e1000e: access multiple PHY registers on same page at the same time
Doing a PHY page select can take a long time, relatively speaking. This
can cause a significant delay when updating a number of PHY registers on
the same page by unnecessarily setting the page for each PHY access. For
example when going to Sx, all the PHY wakeup registers (WUC, RAR[], MTA[],
SHRAR[], IP4AT[], IP6AT[], etc.) on 82577/8/9 need to be updated which
takes a long time which can cause issues when suspending.
This patch introduces new PHY ops function pointers to allow callers to
set the page directly and do any number of PHY accesses on that page.
This feature is currently only implemented for 82577, 82578 and 82579
PHYs for both the normally addressed registers as well as the special-
case addressing of the PHY wakeup registers on page 800. For the latter
registers, the existing function for accessing the wakeup registers has
been divided up into three- 1) enable access to the wakeup register page,
2) perform the register access and 3) disable access to the wakeup register
page. The two functions that enable/disable access to the wakeup register
page are necessarily available to the caller so that the caller can restore
the value of the Port Control (a.k.a. Wakeup Enable) register after the
wakeup register accesses are done.
All instances of writing to multiple PHY registers on the same page are
updated to use this new method and to acquire any PHY locking mechanism
before setting the page and performing the register accesses, and release
the locking mechanism afterward.
Some affiliated magic number cleanup is done as well.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/e1000e/phy.c')
-rw-r--r-- | drivers/net/e1000e/phy.c | 352 |
1 files changed, 229 insertions, 123 deletions
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 484774c13c21..2a6ee13285b1 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c | |||
@@ -36,7 +36,7 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active); | |||
36 | static s32 e1000_wait_autoneg(struct e1000_hw *hw); | 36 | static s32 e1000_wait_autoneg(struct e1000_hw *hw); |
37 | static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg); | 37 | static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg); |
38 | static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, | 38 | static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, |
39 | u16 *data, bool read); | 39 | u16 *data, bool read, bool page_set); |
40 | static u32 e1000_get_phy_addr_for_hv_page(u32 page); | 40 | static u32 e1000_get_phy_addr_for_hv_page(u32 page); |
41 | static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, | 41 | static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, |
42 | u16 *data, bool read); | 42 | u16 *data, bool read); |
@@ -348,6 +348,24 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) | |||
348 | } | 348 | } |
349 | 349 | ||
350 | /** | 350 | /** |
351 | * e1000_set_page_igp - Set page as on IGP-like PHY(s) | ||
352 | * @hw: pointer to the HW structure | ||
353 | * @page: page to set (shifted left when necessary) | ||
354 | * | ||
355 | * Sets PHY page required for PHY register access. Assumes semaphore is | ||
356 | * already acquired. Note, this function sets phy.addr to 1 so the caller | ||
357 | * must set it appropriately (if necessary) after this function returns. | ||
358 | **/ | ||
359 | s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page) | ||
360 | { | ||
361 | e_dbg("Setting page 0x%x\n", page); | ||
362 | |||
363 | hw->phy.addr = 1; | ||
364 | |||
365 | return e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page); | ||
366 | } | ||
367 | |||
368 | /** | ||
351 | * __e1000e_read_phy_reg_igp - Read igp PHY register | 369 | * __e1000e_read_phy_reg_igp - Read igp PHY register |
352 | * @hw: pointer to the HW structure | 370 | * @hw: pointer to the HW structure |
353 | * @offset: register offset to be read | 371 | * @offset: register offset to be read |
@@ -2418,7 +2436,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) | |||
2418 | /* Page 800 works differently than the rest so it has its own func */ | 2436 | /* Page 800 works differently than the rest so it has its own func */ |
2419 | if (page == BM_WUC_PAGE) { | 2437 | if (page == BM_WUC_PAGE) { |
2420 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, | 2438 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, |
2421 | false); | 2439 | false, false); |
2422 | goto out; | 2440 | goto out; |
2423 | } | 2441 | } |
2424 | 2442 | ||
@@ -2477,7 +2495,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) | |||
2477 | /* Page 800 works differently than the rest so it has its own func */ | 2495 | /* Page 800 works differently than the rest so it has its own func */ |
2478 | if (page == BM_WUC_PAGE) { | 2496 | if (page == BM_WUC_PAGE) { |
2479 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, | 2497 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, |
2480 | true); | 2498 | true, false); |
2481 | goto out; | 2499 | goto out; |
2482 | } | 2500 | } |
2483 | 2501 | ||
@@ -2535,7 +2553,7 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) | |||
2535 | /* Page 800 works differently than the rest so it has its own func */ | 2553 | /* Page 800 works differently than the rest so it has its own func */ |
2536 | if (page == BM_WUC_PAGE) { | 2554 | if (page == BM_WUC_PAGE) { |
2537 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, | 2555 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, |
2538 | true); | 2556 | true, false); |
2539 | goto out; | 2557 | goto out; |
2540 | } | 2558 | } |
2541 | 2559 | ||
@@ -2579,7 +2597,7 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) | |||
2579 | /* Page 800 works differently than the rest so it has its own func */ | 2597 | /* Page 800 works differently than the rest so it has its own func */ |
2580 | if (page == BM_WUC_PAGE) { | 2598 | if (page == BM_WUC_PAGE) { |
2581 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, | 2599 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, |
2582 | false); | 2600 | false, false); |
2583 | goto out; | 2601 | goto out; |
2584 | } | 2602 | } |
2585 | 2603 | ||
@@ -2603,104 +2621,163 @@ out: | |||
2603 | } | 2621 | } |
2604 | 2622 | ||
2605 | /** | 2623 | /** |
2606 | * e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register | 2624 | * e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers |
2607 | * @hw: pointer to the HW structure | 2625 | * @hw: pointer to the HW structure |
2608 | * @offset: register offset to be read or written | 2626 | * @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG |
2609 | * @data: pointer to the data to read or write | ||
2610 | * @read: determines if operation is read or write | ||
2611 | * | 2627 | * |
2612 | * Acquires semaphore, if necessary, then reads the PHY register at offset | 2628 | * Assumes semaphore already acquired and phy_reg points to a valid memory |
2613 | * and storing the retrieved information in data. Release any acquired | 2629 | * address to store contents of the BM_WUC_ENABLE_REG register. |
2614 | * semaphores before exiting. Note that procedure to read the wakeup | ||
2615 | * registers are different. It works as such: | ||
2616 | * 1) Set page 769, register 17, bit 2 = 1 | ||
2617 | * 2) Set page to 800 for host (801 if we were manageability) | ||
2618 | * 3) Write the address using the address opcode (0x11) | ||
2619 | * 4) Read or write the data using the data opcode (0x12) | ||
2620 | * 5) Restore 769_17.2 to its original value | ||
2621 | * | ||
2622 | * Assumes semaphore already acquired. | ||
2623 | **/ | 2630 | **/ |
2624 | static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, | 2631 | s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) |
2625 | u16 *data, bool read) | ||
2626 | { | 2632 | { |
2627 | s32 ret_val; | 2633 | s32 ret_val; |
2628 | u16 reg = BM_PHY_REG_NUM(offset); | 2634 | u16 temp; |
2629 | u16 phy_reg = 0; | ||
2630 | 2635 | ||
2631 | /* Gig must be disabled for MDIO accesses to page 800 */ | 2636 | /* All page select, port ctrl and wakeup registers use phy address 1 */ |
2632 | if ((hw->mac.type == e1000_pchlan) && | ||
2633 | (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) | ||
2634 | e_dbg("Attempting to access page 800 while gig enabled.\n"); | ||
2635 | |||
2636 | /* All operations in this function are phy address 1 */ | ||
2637 | hw->phy.addr = 1; | 2637 | hw->phy.addr = 1; |
2638 | 2638 | ||
2639 | /* Set page 769 */ | 2639 | /* Select Port Control Registers page */ |
2640 | e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, | 2640 | ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); |
2641 | (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); | 2641 | if (ret_val) { |
2642 | e_dbg("Could not set Port Control page\n"); | ||
2643 | goto out; | ||
2644 | } | ||
2642 | 2645 | ||
2643 | ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg); | 2646 | ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); |
2644 | if (ret_val) { | 2647 | if (ret_val) { |
2645 | e_dbg("Could not read PHY page 769\n"); | 2648 | e_dbg("Could not read PHY register %d.%d\n", |
2649 | BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); | ||
2646 | goto out; | 2650 | goto out; |
2647 | } | 2651 | } |
2648 | 2652 | ||
2649 | /* First clear bit 4 to avoid a power state change */ | 2653 | /* |
2650 | phy_reg &= ~(BM_WUC_HOST_WU_BIT); | 2654 | * Enable both PHY wakeup mode and Wakeup register page writes. |
2651 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); | 2655 | * Prevent a power state change by disabling ME and Host PHY wakeup. |
2656 | */ | ||
2657 | temp = *phy_reg; | ||
2658 | temp |= BM_WUC_ENABLE_BIT; | ||
2659 | temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT); | ||
2660 | |||
2661 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp); | ||
2652 | if (ret_val) { | 2662 | if (ret_val) { |
2653 | e_dbg("Could not clear PHY page 769 bit 4\n"); | 2663 | e_dbg("Could not write PHY register %d.%d\n", |
2664 | BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); | ||
2654 | goto out; | 2665 | goto out; |
2655 | } | 2666 | } |
2656 | 2667 | ||
2657 | /* Write bit 2 = 1, and clear bit 4 to 769_17 */ | 2668 | /* Select Host Wakeup Registers page */ |
2658 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, | 2669 | ret_val = e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT)); |
2659 | phy_reg | BM_WUC_ENABLE_BIT); | 2670 | |
2671 | /* caller now able to write registers on the Wakeup registers page */ | ||
2672 | out: | ||
2673 | return ret_val; | ||
2674 | } | ||
2675 | |||
2676 | /** | ||
2677 | * e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs | ||
2678 | * @hw: pointer to the HW structure | ||
2679 | * @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG | ||
2680 | * | ||
2681 | * Restore BM_WUC_ENABLE_REG to its original value. | ||
2682 | * | ||
2683 | * Assumes semaphore already acquired and *phy_reg is the contents of the | ||
2684 | * BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by | ||
2685 | * caller. | ||
2686 | **/ | ||
2687 | s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) | ||
2688 | { | ||
2689 | s32 ret_val = 0; | ||
2690 | |||
2691 | /* Select Port Control Registers page */ | ||
2692 | ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); | ||
2660 | if (ret_val) { | 2693 | if (ret_val) { |
2661 | e_dbg("Could not write PHY page 769 bit 2\n"); | 2694 | e_dbg("Could not set Port Control page\n"); |
2662 | goto out; | 2695 | goto out; |
2663 | } | 2696 | } |
2664 | 2697 | ||
2665 | /* Select page 800 */ | 2698 | /* Restore 769.17 to its original value */ |
2666 | ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, | 2699 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg); |
2667 | (BM_WUC_PAGE << IGP_PAGE_SHIFT)); | 2700 | if (ret_val) |
2701 | e_dbg("Could not restore PHY register %d.%d\n", | ||
2702 | BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); | ||
2703 | out: | ||
2704 | return ret_val; | ||
2705 | } | ||
2668 | 2706 | ||
2669 | /* Write the page 800 offset value using opcode 0x11 */ | 2707 | /** |
2708 | * e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register | ||
2709 | * @hw: pointer to the HW structure | ||
2710 | * @offset: register offset to be read or written | ||
2711 | * @data: pointer to the data to read or write | ||
2712 | * @read: determines if operation is read or write | ||
2713 | * @page_set: BM_WUC_PAGE already set and access enabled | ||
2714 | * | ||
2715 | * Read the PHY register at offset and store the retrieved information in | ||
2716 | * data, or write data to PHY register at offset. Note the procedure to | ||
2717 | * access the PHY wakeup registers is different than reading the other PHY | ||
2718 | * registers. It works as such: | ||
2719 | * 1) Set 769.17.2 (page 769, register 17, bit 2) = 1 | ||
2720 | * 2) Set page to 800 for host (801 if we were manageability) | ||
2721 | * 3) Write the address using the address opcode (0x11) | ||
2722 | * 4) Read or write the data using the data opcode (0x12) | ||
2723 | * 5) Restore 769.17.2 to its original value | ||
2724 | * | ||
2725 | * Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and | ||
2726 | * step 5 is done by e1000_disable_phy_wakeup_reg_access_bm(). | ||
2727 | * | ||
2728 | * Assumes semaphore is already acquired. When page_set==true, assumes | ||
2729 | * the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack | ||
2730 | * is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()). | ||
2731 | **/ | ||
2732 | static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, | ||
2733 | u16 *data, bool read, bool page_set) | ||
2734 | { | ||
2735 | s32 ret_val; | ||
2736 | u16 reg = BM_PHY_REG_NUM(offset); | ||
2737 | u16 page = BM_PHY_REG_PAGE(offset); | ||
2738 | u16 phy_reg = 0; | ||
2739 | |||
2740 | /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */ | ||
2741 | if ((hw->mac.type == e1000_pchlan) && | ||
2742 | (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) | ||
2743 | e_dbg("Attempting to access page %d while gig enabled.\n", | ||
2744 | page); | ||
2745 | |||
2746 | if (!page_set) { | ||
2747 | /* Enable access to PHY wakeup registers */ | ||
2748 | ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg); | ||
2749 | if (ret_val) { | ||
2750 | e_dbg("Could not enable PHY wakeup reg access\n"); | ||
2751 | goto out; | ||
2752 | } | ||
2753 | } | ||
2754 | |||
2755 | e_dbg("Accessing PHY page %d reg 0x%x\n", page, reg); | ||
2756 | |||
2757 | /* Write the Wakeup register page offset value using opcode 0x11 */ | ||
2670 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); | 2758 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); |
2671 | if (ret_val) { | 2759 | if (ret_val) { |
2672 | e_dbg("Could not write address opcode to page 800\n"); | 2760 | e_dbg("Could not write address opcode to page %d\n", page); |
2673 | goto out; | 2761 | goto out; |
2674 | } | 2762 | } |
2675 | 2763 | ||
2676 | if (read) { | 2764 | if (read) { |
2677 | /* Read the page 800 value using opcode 0x12 */ | 2765 | /* Read the Wakeup register page value using opcode 0x12 */ |
2678 | ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, | 2766 | ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, |
2679 | data); | 2767 | data); |
2680 | } else { | 2768 | } else { |
2681 | /* Write the page 800 value using opcode 0x12 */ | 2769 | /* Write the Wakeup register page value using opcode 0x12 */ |
2682 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, | 2770 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, |
2683 | *data); | 2771 | *data); |
2684 | } | 2772 | } |
2685 | 2773 | ||
2686 | if (ret_val) { | 2774 | if (ret_val) { |
2687 | e_dbg("Could not access data value from page 800\n"); | 2775 | e_dbg("Could not access PHY reg %d.%d\n", page, reg); |
2688 | goto out; | 2776 | goto out; |
2689 | } | 2777 | } |
2690 | 2778 | ||
2691 | /* | 2779 | if (!page_set) |
2692 | * Restore 769_17.2 to its original value | 2780 | ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg); |
2693 | * Set page 769 | ||
2694 | */ | ||
2695 | e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, | ||
2696 | (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); | ||
2697 | |||
2698 | /* Clear 769_17.2 */ | ||
2699 | ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); | ||
2700 | if (ret_val) { | ||
2701 | e_dbg("Could not clear PHY page 769 bit 2\n"); | ||
2702 | goto out; | ||
2703 | } | ||
2704 | 2781 | ||
2705 | out: | 2782 | out: |
2706 | return ret_val; | 2783 | return ret_val; |
@@ -2792,11 +2869,12 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) | |||
2792 | * semaphore before exiting. | 2869 | * semaphore before exiting. |
2793 | **/ | 2870 | **/ |
2794 | static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, | 2871 | static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, |
2795 | bool locked) | 2872 | bool locked, bool page_set) |
2796 | { | 2873 | { |
2797 | s32 ret_val; | 2874 | s32 ret_val; |
2798 | u16 page = BM_PHY_REG_PAGE(offset); | 2875 | u16 page = BM_PHY_REG_PAGE(offset); |
2799 | u16 reg = BM_PHY_REG_NUM(offset); | 2876 | u16 reg = BM_PHY_REG_NUM(offset); |
2877 | u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); | ||
2800 | 2878 | ||
2801 | if (!locked) { | 2879 | if (!locked) { |
2802 | ret_val = hw->phy.ops.acquire(hw); | 2880 | ret_val = hw->phy.ops.acquire(hw); |
@@ -2806,8 +2884,8 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, | |||
2806 | 2884 | ||
2807 | /* Page 800 works differently than the rest so it has its own func */ | 2885 | /* Page 800 works differently than the rest so it has its own func */ |
2808 | if (page == BM_WUC_PAGE) { | 2886 | if (page == BM_WUC_PAGE) { |
2809 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, | 2887 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, |
2810 | data, true); | 2888 | true, page_set); |
2811 | goto out; | 2889 | goto out; |
2812 | } | 2890 | } |
2813 | 2891 | ||
@@ -2817,26 +2895,25 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, | |||
2817 | goto out; | 2895 | goto out; |
2818 | } | 2896 | } |
2819 | 2897 | ||
2820 | hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); | 2898 | if (!page_set) { |
2821 | 2899 | if (page == HV_INTC_FC_PAGE_START) | |
2822 | if (page == HV_INTC_FC_PAGE_START) | 2900 | page = 0; |
2823 | page = 0; | ||
2824 | 2901 | ||
2825 | if (reg > MAX_PHY_MULTI_PAGE_REG) { | 2902 | if (reg > MAX_PHY_MULTI_PAGE_REG) { |
2826 | u32 phy_addr = hw->phy.addr; | 2903 | /* Page is shifted left, PHY expects (page x 32) */ |
2904 | ret_val = e1000_set_page_igp(hw, | ||
2905 | (page << IGP_PAGE_SHIFT)); | ||
2827 | 2906 | ||
2828 | hw->phy.addr = 1; | 2907 | hw->phy.addr = phy_addr; |
2829 | |||
2830 | /* Page is shifted left, PHY expects (page x 32) */ | ||
2831 | ret_val = e1000e_write_phy_reg_mdic(hw, | ||
2832 | IGP01E1000_PHY_PAGE_SELECT, | ||
2833 | (page << IGP_PAGE_SHIFT)); | ||
2834 | hw->phy.addr = phy_addr; | ||
2835 | 2908 | ||
2836 | if (ret_val) | 2909 | if (ret_val) |
2837 | goto out; | 2910 | goto out; |
2911 | } | ||
2838 | } | 2912 | } |
2839 | 2913 | ||
2914 | e_dbg("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page, | ||
2915 | page << IGP_PAGE_SHIFT, reg); | ||
2916 | |||
2840 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, | 2917 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, |
2841 | data); | 2918 | data); |
2842 | out: | 2919 | out: |
@@ -2858,7 +2935,7 @@ out: | |||
2858 | **/ | 2935 | **/ |
2859 | s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) | 2936 | s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) |
2860 | { | 2937 | { |
2861 | return __e1000_read_phy_reg_hv(hw, offset, data, false); | 2938 | return __e1000_read_phy_reg_hv(hw, offset, data, false, false); |
2862 | } | 2939 | } |
2863 | 2940 | ||
2864 | /** | 2941 | /** |
@@ -2872,7 +2949,21 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) | |||
2872 | **/ | 2949 | **/ |
2873 | s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data) | 2950 | s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data) |
2874 | { | 2951 | { |
2875 | return __e1000_read_phy_reg_hv(hw, offset, data, true); | 2952 | return __e1000_read_phy_reg_hv(hw, offset, data, true, false); |
2953 | } | ||
2954 | |||
2955 | /** | ||
2956 | * e1000_read_phy_reg_page_hv - Read HV PHY register | ||
2957 | * @hw: pointer to the HW structure | ||
2958 | * @offset: register offset to write to | ||
2959 | * @data: data to write at register offset | ||
2960 | * | ||
2961 | * Reads the PHY register at offset and stores the retrieved information | ||
2962 | * in data. Assumes semaphore already acquired and page already set. | ||
2963 | **/ | ||
2964 | s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data) | ||
2965 | { | ||
2966 | return __e1000_read_phy_reg_hv(hw, offset, data, true, true); | ||
2876 | } | 2967 | } |
2877 | 2968 | ||
2878 | /** | 2969 | /** |
@@ -2886,11 +2977,12 @@ s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data) | |||
2886 | * at the offset. Release any acquired semaphores before exiting. | 2977 | * at the offset. Release any acquired semaphores before exiting. |
2887 | **/ | 2978 | **/ |
2888 | static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, | 2979 | static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, |
2889 | bool locked) | 2980 | bool locked, bool page_set) |
2890 | { | 2981 | { |
2891 | s32 ret_val; | 2982 | s32 ret_val; |
2892 | u16 page = BM_PHY_REG_PAGE(offset); | 2983 | u16 page = BM_PHY_REG_PAGE(offset); |
2893 | u16 reg = BM_PHY_REG_NUM(offset); | 2984 | u16 reg = BM_PHY_REG_NUM(offset); |
2985 | u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); | ||
2894 | 2986 | ||
2895 | if (!locked) { | 2987 | if (!locked) { |
2896 | ret_val = hw->phy.ops.acquire(hw); | 2988 | ret_val = hw->phy.ops.acquire(hw); |
@@ -2900,8 +2992,8 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, | |||
2900 | 2992 | ||
2901 | /* Page 800 works differently than the rest so it has its own func */ | 2993 | /* Page 800 works differently than the rest so it has its own func */ |
2902 | if (page == BM_WUC_PAGE) { | 2994 | if (page == BM_WUC_PAGE) { |
2903 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, | 2995 | ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, |
2904 | &data, false); | 2996 | false, page_set); |
2905 | goto out; | 2997 | goto out; |
2906 | } | 2998 | } |
2907 | 2999 | ||
@@ -2911,42 +3003,41 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, | |||
2911 | goto out; | 3003 | goto out; |
2912 | } | 3004 | } |
2913 | 3005 | ||
2914 | hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); | 3006 | if (!page_set) { |
2915 | 3007 | if (page == HV_INTC_FC_PAGE_START) | |
2916 | if (page == HV_INTC_FC_PAGE_START) | 3008 | page = 0; |
2917 | page = 0; | ||
2918 | |||
2919 | /* | ||
2920 | * Workaround MDIO accesses being disabled after entering IEEE Power | ||
2921 | * Down (whenever bit 11 of the PHY Control register is set) | ||
2922 | */ | ||
2923 | if ((hw->phy.type == e1000_phy_82578) && | ||
2924 | (hw->phy.revision >= 1) && | ||
2925 | (hw->phy.addr == 2) && | ||
2926 | ((MAX_PHY_REG_ADDRESS & reg) == 0) && | ||
2927 | (data & (1 << 11))) { | ||
2928 | u16 data2 = 0x7EFF; | ||
2929 | ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3, | ||
2930 | &data2, false); | ||
2931 | if (ret_val) | ||
2932 | goto out; | ||
2933 | } | ||
2934 | 3009 | ||
2935 | if (reg > MAX_PHY_MULTI_PAGE_REG) { | 3010 | /* |
2936 | u32 phy_addr = hw->phy.addr; | 3011 | * Workaround MDIO accesses being disabled after entering IEEE |
3012 | * Power Down (when bit 11 of the PHY Control register is set) | ||
3013 | */ | ||
3014 | if ((hw->phy.type == e1000_phy_82578) && | ||
3015 | (hw->phy.revision >= 1) && | ||
3016 | (hw->phy.addr == 2) && | ||
3017 | ((MAX_PHY_REG_ADDRESS & reg) == 0) && (data & (1 << 11))) { | ||
3018 | u16 data2 = 0x7EFF; | ||
3019 | ret_val = e1000_access_phy_debug_regs_hv(hw, | ||
3020 | (1 << 6) | 0x3, | ||
3021 | &data2, false); | ||
3022 | if (ret_val) | ||
3023 | goto out; | ||
3024 | } | ||
2937 | 3025 | ||
2938 | hw->phy.addr = 1; | 3026 | if (reg > MAX_PHY_MULTI_PAGE_REG) { |
3027 | /* Page is shifted left, PHY expects (page x 32) */ | ||
3028 | ret_val = e1000_set_page_igp(hw, | ||
3029 | (page << IGP_PAGE_SHIFT)); | ||
2939 | 3030 | ||
2940 | /* Page is shifted left, PHY expects (page x 32) */ | 3031 | hw->phy.addr = phy_addr; |
2941 | ret_val = e1000e_write_phy_reg_mdic(hw, | ||
2942 | IGP01E1000_PHY_PAGE_SELECT, | ||
2943 | (page << IGP_PAGE_SHIFT)); | ||
2944 | hw->phy.addr = phy_addr; | ||
2945 | 3032 | ||
2946 | if (ret_val) | 3033 | if (ret_val) |
2947 | goto out; | 3034 | goto out; |
3035 | } | ||
2948 | } | 3036 | } |
2949 | 3037 | ||
3038 | e_dbg("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page, | ||
3039 | page << IGP_PAGE_SHIFT, reg); | ||
3040 | |||
2950 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, | 3041 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, |
2951 | data); | 3042 | data); |
2952 | 3043 | ||
@@ -2968,7 +3059,7 @@ out: | |||
2968 | **/ | 3059 | **/ |
2969 | s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) | 3060 | s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) |
2970 | { | 3061 | { |
2971 | return __e1000_write_phy_reg_hv(hw, offset, data, false); | 3062 | return __e1000_write_phy_reg_hv(hw, offset, data, false, false); |
2972 | } | 3063 | } |
2973 | 3064 | ||
2974 | /** | 3065 | /** |
@@ -2982,7 +3073,21 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) | |||
2982 | **/ | 3073 | **/ |
2983 | s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data) | 3074 | s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data) |
2984 | { | 3075 | { |
2985 | return __e1000_write_phy_reg_hv(hw, offset, data, true); | 3076 | return __e1000_write_phy_reg_hv(hw, offset, data, true, false); |
3077 | } | ||
3078 | |||
3079 | /** | ||
3080 | * e1000_write_phy_reg_page_hv - Write HV PHY register | ||
3081 | * @hw: pointer to the HW structure | ||
3082 | * @offset: register offset to write to | ||
3083 | * @data: data to write at register offset | ||
3084 | * | ||
3085 | * Writes the data to PHY register at the offset. Assumes semaphore | ||
3086 | * already acquired and page already set. | ||
3087 | **/ | ||
3088 | s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data) | ||
3089 | { | ||
3090 | return __e1000_write_phy_reg_hv(hw, offset, data, true, true); | ||
2986 | } | 3091 | } |
2987 | 3092 | ||
2988 | /** | 3093 | /** |
@@ -3004,11 +3109,12 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page) | |||
3004 | * @hw: pointer to the HW structure | 3109 | * @hw: pointer to the HW structure |
3005 | * @offset: register offset to be read or written | 3110 | * @offset: register offset to be read or written |
3006 | * @data: pointer to the data to be read or written | 3111 | * @data: pointer to the data to be read or written |
3007 | * @read: determines if operation is read or written | 3112 | * @read: determines if operation is read or write |
3008 | * | 3113 | * |
3009 | * Reads the PHY register at offset and stores the retreived information | 3114 | * Reads the PHY register at offset and stores the retreived information |
3010 | * in data. Assumes semaphore already acquired. Note that the procedure | 3115 | * in data. Assumes semaphore already acquired. Note that the procedure |
3011 | * to read these regs uses the address port and data port to read/write. | 3116 | * to access these regs uses the address port and data port to read/write. |
3117 | * These accesses done with PHY address 2 and without using pages. | ||
3012 | **/ | 3118 | **/ |
3013 | static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, | 3119 | static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, |
3014 | u16 *data, bool read) | 3120 | u16 *data, bool read) |
@@ -3028,7 +3134,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, | |||
3028 | /* masking with 0x3F to remove the page from offset */ | 3134 | /* masking with 0x3F to remove the page from offset */ |
3029 | ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F); | 3135 | ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F); |
3030 | if (ret_val) { | 3136 | if (ret_val) { |
3031 | e_dbg("Could not write PHY the HV address register\n"); | 3137 | e_dbg("Could not write the Address Offset port register\n"); |
3032 | goto out; | 3138 | goto out; |
3033 | } | 3139 | } |
3034 | 3140 | ||
@@ -3039,7 +3145,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, | |||
3039 | ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data); | 3145 | ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data); |
3040 | 3146 | ||
3041 | if (ret_val) { | 3147 | if (ret_val) { |
3042 | e_dbg("Could not read data value from HV data register\n"); | 3148 | e_dbg("Could not access the Data port register\n"); |
3043 | goto out; | 3149 | goto out; |
3044 | } | 3150 | } |
3045 | 3151 | ||