diff options
Diffstat (limited to 'drivers/net/e1000e/ich8lan.c')
-rw-r--r-- | drivers/net/e1000e/ich8lan.c | 187 |
1 files changed, 170 insertions, 17 deletions
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 095ffa56ed94..51ddb04ab195 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c | |||
@@ -140,6 +140,9 @@ | |||
140 | #define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ | 140 | #define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ |
141 | #define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ | 141 | #define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ |
142 | 142 | ||
143 | #define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ | ||
144 | #define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ | ||
145 | |||
143 | /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ | 146 | /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ |
144 | /* Offset 04h HSFSTS */ | 147 | /* Offset 04h HSFSTS */ |
145 | union ich8_hws_flash_status { | 148 | union ich8_hws_flash_status { |
@@ -220,6 +223,8 @@ static s32 e1000_led_on_pchlan(struct e1000_hw *hw); | |||
220 | static s32 e1000_led_off_pchlan(struct e1000_hw *hw); | 223 | static s32 e1000_led_off_pchlan(struct e1000_hw *hw); |
221 | static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); | 224 | static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); |
222 | static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); | 225 | static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); |
226 | static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); | ||
227 | static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); | ||
223 | 228 | ||
224 | static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) | 229 | static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) |
225 | { | 230 | { |
@@ -495,14 +500,6 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) | |||
495 | goto out; | 500 | goto out; |
496 | } | 501 | } |
497 | 502 | ||
498 | if (hw->mac.type == e1000_pchlan) { | ||
499 | ret_val = e1000e_write_kmrn_reg(hw, | ||
500 | E1000_KMRNCTRLSTA_K1_CONFIG, | ||
501 | E1000_KMRNCTRLSTA_K1_ENABLE); | ||
502 | if (ret_val) | ||
503 | goto out; | ||
504 | } | ||
505 | |||
506 | /* | 503 | /* |
507 | * First we want to see if the MII Status Register reports | 504 | * First we want to see if the MII Status Register reports |
508 | * link. If so, then we want to get the current speed/duplex | 505 | * link. If so, then we want to get the current speed/duplex |
@@ -512,6 +509,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) | |||
512 | if (ret_val) | 509 | if (ret_val) |
513 | goto out; | 510 | goto out; |
514 | 511 | ||
512 | if (hw->mac.type == e1000_pchlan) { | ||
513 | ret_val = e1000_k1_gig_workaround_hv(hw, link); | ||
514 | if (ret_val) | ||
515 | goto out; | ||
516 | } | ||
517 | |||
515 | if (!link) | 518 | if (!link) |
516 | goto out; /* No link detected */ | 519 | goto out; /* No link detected */ |
517 | 520 | ||
@@ -929,6 +932,141 @@ out: | |||
929 | } | 932 | } |
930 | 933 | ||
931 | /** | 934 | /** |
935 | * e1000_k1_gig_workaround_hv - K1 Si workaround | ||
936 | * @hw: pointer to the HW structure | ||
937 | * @link: link up bool flag | ||
938 | * | ||
939 | * If K1 is enabled for 1Gbps, the MAC might stall when transitioning | ||
940 | * from a lower speed. This workaround disables K1 whenever link is at 1Gig | ||
941 | * If link is down, the function will restore the default K1 setting located | ||
942 | * in the NVM. | ||
943 | **/ | ||
944 | static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) | ||
945 | { | ||
946 | s32 ret_val = 0; | ||
947 | u16 status_reg = 0; | ||
948 | bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled; | ||
949 | |||
950 | if (hw->mac.type != e1000_pchlan) | ||
951 | goto out; | ||
952 | |||
953 | /* Wrap the whole flow with the sw flag */ | ||
954 | ret_val = hw->phy.ops.acquire_phy(hw); | ||
955 | if (ret_val) | ||
956 | goto out; | ||
957 | |||
958 | /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */ | ||
959 | if (link) { | ||
960 | if (hw->phy.type == e1000_phy_82578) { | ||
961 | ret_val = hw->phy.ops.read_phy_reg_locked(hw, | ||
962 | BM_CS_STATUS, | ||
963 | &status_reg); | ||
964 | if (ret_val) | ||
965 | goto release; | ||
966 | |||
967 | status_reg &= BM_CS_STATUS_LINK_UP | | ||
968 | BM_CS_STATUS_RESOLVED | | ||
969 | BM_CS_STATUS_SPEED_MASK; | ||
970 | |||
971 | if (status_reg == (BM_CS_STATUS_LINK_UP | | ||
972 | BM_CS_STATUS_RESOLVED | | ||
973 | BM_CS_STATUS_SPEED_1000)) | ||
974 | k1_enable = false; | ||
975 | } | ||
976 | |||
977 | if (hw->phy.type == e1000_phy_82577) { | ||
978 | ret_val = hw->phy.ops.read_phy_reg_locked(hw, | ||
979 | HV_M_STATUS, | ||
980 | &status_reg); | ||
981 | if (ret_val) | ||
982 | goto release; | ||
983 | |||
984 | status_reg &= HV_M_STATUS_LINK_UP | | ||
985 | HV_M_STATUS_AUTONEG_COMPLETE | | ||
986 | HV_M_STATUS_SPEED_MASK; | ||
987 | |||
988 | if (status_reg == (HV_M_STATUS_LINK_UP | | ||
989 | HV_M_STATUS_AUTONEG_COMPLETE | | ||
990 | HV_M_STATUS_SPEED_1000)) | ||
991 | k1_enable = false; | ||
992 | } | ||
993 | |||
994 | /* Link stall fix for link up */ | ||
995 | ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19), | ||
996 | 0x0100); | ||
997 | if (ret_val) | ||
998 | goto release; | ||
999 | |||
1000 | } else { | ||
1001 | /* Link stall fix for link down */ | ||
1002 | ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19), | ||
1003 | 0x4100); | ||
1004 | if (ret_val) | ||
1005 | goto release; | ||
1006 | } | ||
1007 | |||
1008 | ret_val = e1000_configure_k1_ich8lan(hw, k1_enable); | ||
1009 | |||
1010 | release: | ||
1011 | hw->phy.ops.release_phy(hw); | ||
1012 | out: | ||
1013 | return ret_val; | ||
1014 | } | ||
1015 | |||
1016 | /** | ||
1017 | * e1000_configure_k1_ich8lan - Configure K1 power state | ||
1018 | * @hw: pointer to the HW structure | ||
1019 | * @enable: K1 state to configure | ||
1020 | * | ||
1021 | * Configure the K1 power state based on the provided parameter. | ||
1022 | * Assumes semaphore already acquired. | ||
1023 | * | ||
1024 | * Success returns 0, Failure returns -E1000_ERR_PHY (-2) | ||
1025 | **/ | ||
1026 | static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) | ||
1027 | { | ||
1028 | s32 ret_val = 0; | ||
1029 | u32 ctrl_reg = 0; | ||
1030 | u32 ctrl_ext = 0; | ||
1031 | u32 reg = 0; | ||
1032 | u16 kmrn_reg = 0; | ||
1033 | |||
1034 | ret_val = e1000e_read_kmrn_reg_locked(hw, | ||
1035 | E1000_KMRNCTRLSTA_K1_CONFIG, | ||
1036 | &kmrn_reg); | ||
1037 | if (ret_val) | ||
1038 | goto out; | ||
1039 | |||
1040 | if (k1_enable) | ||
1041 | kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE; | ||
1042 | else | ||
1043 | kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE; | ||
1044 | |||
1045 | ret_val = e1000e_write_kmrn_reg_locked(hw, | ||
1046 | E1000_KMRNCTRLSTA_K1_CONFIG, | ||
1047 | kmrn_reg); | ||
1048 | if (ret_val) | ||
1049 | goto out; | ||
1050 | |||
1051 | udelay(20); | ||
1052 | ctrl_ext = er32(CTRL_EXT); | ||
1053 | ctrl_reg = er32(CTRL); | ||
1054 | |||
1055 | reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); | ||
1056 | reg |= E1000_CTRL_FRCSPD; | ||
1057 | ew32(CTRL, reg); | ||
1058 | |||
1059 | ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS); | ||
1060 | udelay(20); | ||
1061 | ew32(CTRL, ctrl_reg); | ||
1062 | ew32(CTRL_EXT, ctrl_ext); | ||
1063 | udelay(20); | ||
1064 | |||
1065 | out: | ||
1066 | return ret_val; | ||
1067 | } | ||
1068 | |||
1069 | /** | ||
932 | * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration | 1070 | * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration |
933 | * @hw: pointer to the HW structure | 1071 | * @hw: pointer to the HW structure |
934 | * @d0_state: boolean if entering d0 or d3 device state | 1072 | * @d0_state: boolean if entering d0 or d3 device state |
@@ -1030,10 +1168,20 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) | |||
1030 | ret_val = hw->phy.ops.acquire_phy(hw); | 1168 | ret_val = hw->phy.ops.acquire_phy(hw); |
1031 | if (ret_val) | 1169 | if (ret_val) |
1032 | return ret_val; | 1170 | return ret_val; |
1171 | |||
1033 | hw->phy.addr = 1; | 1172 | hw->phy.addr = 1; |
1034 | e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); | 1173 | ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); |
1174 | if (ret_val) | ||
1175 | goto out; | ||
1035 | hw->phy.ops.release_phy(hw); | 1176 | hw->phy.ops.release_phy(hw); |
1036 | 1177 | ||
1178 | /* | ||
1179 | * Configure the K1 Si workaround during phy reset assuming there is | ||
1180 | * link so that it disables K1 if link is in 1Gbps. | ||
1181 | */ | ||
1182 | ret_val = e1000_k1_gig_workaround_hv(hw, true); | ||
1183 | |||
1184 | out: | ||
1037 | return ret_val; | 1185 | return ret_val; |
1038 | } | 1186 | } |
1039 | 1187 | ||
@@ -2435,6 +2583,7 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) | |||
2435 | **/ | 2583 | **/ |
2436 | static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) | 2584 | static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) |
2437 | { | 2585 | { |
2586 | struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; | ||
2438 | u16 reg; | 2587 | u16 reg; |
2439 | u32 ctrl, icr, kab; | 2588 | u32 ctrl, icr, kab; |
2440 | s32 ret_val; | 2589 | s32 ret_val; |
@@ -2470,6 +2619,18 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) | |||
2470 | ew32(PBS, E1000_PBS_16K); | 2619 | ew32(PBS, E1000_PBS_16K); |
2471 | } | 2620 | } |
2472 | 2621 | ||
2622 | if (hw->mac.type == e1000_pchlan) { | ||
2623 | /* Save the NVM K1 bit setting*/ | ||
2624 | ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, ®); | ||
2625 | if (ret_val) | ||
2626 | return ret_val; | ||
2627 | |||
2628 | if (reg & E1000_NVM_K1_ENABLE) | ||
2629 | dev_spec->nvm_k1_enabled = true; | ||
2630 | else | ||
2631 | dev_spec->nvm_k1_enabled = false; | ||
2632 | } | ||
2633 | |||
2473 | ctrl = er32(CTRL); | 2634 | ctrl = er32(CTRL); |
2474 | 2635 | ||
2475 | if (!e1000_check_reset_block(hw)) { | 2636 | if (!e1000_check_reset_block(hw)) { |
@@ -2847,14 +3008,6 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, | |||
2847 | if (ret_val) | 3008 | if (ret_val) |
2848 | return ret_val; | 3009 | return ret_val; |
2849 | 3010 | ||
2850 | if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) { | ||
2851 | ret_val = e1000e_write_kmrn_reg(hw, | ||
2852 | E1000_KMRNCTRLSTA_K1_CONFIG, | ||
2853 | E1000_KMRNCTRLSTA_K1_DISABLE); | ||
2854 | if (ret_val) | ||
2855 | return ret_val; | ||
2856 | } | ||
2857 | |||
2858 | if ((hw->mac.type == e1000_ich8lan) && | 3011 | if ((hw->mac.type == e1000_ich8lan) && |
2859 | (hw->phy.type == e1000_phy_igp_3) && | 3012 | (hw->phy.type == e1000_phy_igp_3) && |
2860 | (*speed == SPEED_1000)) { | 3013 | (*speed == SPEED_1000)) { |