aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000e/ich8lan.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-01-23 03:31:06 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-23 03:31:06 -0500
commit51c24aaacaea90c8e87f1dec75a2ac7622b593f8 (patch)
tree9f54936c87764bef75e97395cb56b7d1e0df24c6 /drivers/net/e1000e/ich8lan.c
parent4276e47e2d1c85a2477caf0d22b91c4f2377fba8 (diff)
parent6be325719b3e54624397e413efd4b33a997e55a3 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Diffstat (limited to 'drivers/net/e1000e/ich8lan.c')
-rw-r--r--drivers/net/e1000e/ich8lan.c76
1 files changed, 71 insertions, 5 deletions
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 061cd100aac2..54d03a0ce3ce 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -138,6 +138,10 @@
138#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ 138#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */
139#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ 139#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */
140 140
141/* KMRN Mode Control */
142#define HV_KMRN_MODE_CTRL PHY_REG(769, 16)
143#define HV_KMRN_MDIO_SLOW 0x0400
144
141/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ 145/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
142/* Offset 04h HSFSTS */ 146/* Offset 04h HSFSTS */
143union ich8_hws_flash_status { 147union ich8_hws_flash_status {
@@ -219,6 +223,7 @@ static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active);
219static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); 223static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw);
220static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); 224static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw);
221static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); 225static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
226static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);
222 227
223static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) 228static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
224{ 229{
@@ -270,7 +275,21 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
270 phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 275 phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
271 276
272 phy->id = e1000_phy_unknown; 277 phy->id = e1000_phy_unknown;
273 e1000e_get_phy_id(hw); 278 ret_val = e1000e_get_phy_id(hw);
279 if (ret_val)
280 goto out;
281 if ((phy->id == 0) || (phy->id == PHY_REVISION_MASK)) {
282 /*
283 * In case the PHY needs to be in mdio slow mode (eg. 82577),
284 * set slow mode and try to get the PHY id again.
285 */
286 ret_val = e1000_set_mdio_slow_mode_hv(hw);
287 if (ret_val)
288 goto out;
289 ret_val = e1000e_get_phy_id(hw);
290 if (ret_val)
291 goto out;
292 }
274 phy->type = e1000e_get_phy_type_from_id(phy->id); 293 phy->type = e1000e_get_phy_type_from_id(phy->id);
275 294
276 switch (phy->type) { 295 switch (phy->type) {
@@ -292,6 +311,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
292 break; 311 break;
293 } 312 }
294 313
314out:
295 return ret_val; 315 return ret_val;
296} 316}
297 317
@@ -1076,16 +1096,44 @@ out:
1076 1096
1077 1097
1078/** 1098/**
1099 * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode
1100 * @hw: pointer to the HW structure
1101 **/
1102static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw)
1103{
1104 s32 ret_val;
1105 u16 data;
1106
1107 ret_val = e1e_rphy(hw, HV_KMRN_MODE_CTRL, &data);
1108 if (ret_val)
1109 return ret_val;
1110
1111 data |= HV_KMRN_MDIO_SLOW;
1112
1113 ret_val = e1e_wphy(hw, HV_KMRN_MODE_CTRL, data);
1114
1115 return ret_val;
1116}
1117
1118/**
1079 * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be 1119 * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be
1080 * done after every PHY reset. 1120 * done after every PHY reset.
1081 **/ 1121 **/
1082static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) 1122static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
1083{ 1123{
1084 s32 ret_val = 0; 1124 s32 ret_val = 0;
1125 u16 phy_data;
1085 1126
1086 if (hw->mac.type != e1000_pchlan) 1127 if (hw->mac.type != e1000_pchlan)
1087 return ret_val; 1128 return ret_val;
1088 1129
1130 /* Set MDIO slow mode before any other MDIO access */
1131 if (hw->phy.type == e1000_phy_82577) {
1132 ret_val = e1000_set_mdio_slow_mode_hv(hw);
1133 if (ret_val)
1134 goto out;
1135 }
1136
1089 if (((hw->phy.type == e1000_phy_82577) && 1137 if (((hw->phy.type == e1000_phy_82577) &&
1090 ((hw->phy.revision == 1) || (hw->phy.revision == 2))) || 1138 ((hw->phy.revision == 1) || (hw->phy.revision == 2))) ||
1091 ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) { 1139 ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) {
@@ -1118,16 +1166,32 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
1118 1166
1119 hw->phy.addr = 1; 1167 hw->phy.addr = 1;
1120 ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); 1168 ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
1169 hw->phy.ops.release(hw);
1121 if (ret_val) 1170 if (ret_val)
1122 goto out; 1171 goto out;
1123 hw->phy.ops.release(hw);
1124 1172
1125 /* 1173 /*
1126 * Configure the K1 Si workaround during phy reset assuming there is 1174 * Configure the K1 Si workaround during phy reset assuming there is
1127 * link so that it disables K1 if link is in 1Gbps. 1175 * link so that it disables K1 if link is in 1Gbps.
1128 */ 1176 */
1129 ret_val = e1000_k1_gig_workaround_hv(hw, true); 1177 ret_val = e1000_k1_gig_workaround_hv(hw, true);
1178 if (ret_val)
1179 goto out;
1130 1180
1181 /* Workaround for link disconnects on a busy hub in half duplex */
1182 ret_val = hw->phy.ops.acquire(hw);
1183 if (ret_val)
1184 goto out;
1185 ret_val = hw->phy.ops.read_reg_locked(hw,
1186 PHY_REG(BM_PORT_CTRL_PAGE, 17),
1187 &phy_data);
1188 if (ret_val)
1189 goto release;
1190 ret_val = hw->phy.ops.write_reg_locked(hw,
1191 PHY_REG(BM_PORT_CTRL_PAGE, 17),
1192 phy_data & 0x00FF);
1193release:
1194 hw->phy.ops.release(hw);
1131out: 1195out:
1132 return ret_val; 1196 return ret_val;
1133} 1197}
@@ -1184,6 +1248,7 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
1184 /* Allow time for h/w to get to a quiescent state after reset */ 1248 /* Allow time for h/w to get to a quiescent state after reset */
1185 mdelay(10); 1249 mdelay(10);
1186 1250
1251 /* Perform any necessary post-reset workarounds */
1187 if (hw->mac.type == e1000_pchlan) { 1252 if (hw->mac.type == e1000_pchlan) {
1188 ret_val = e1000_hv_phy_workarounds_ich8lan(hw); 1253 ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
1189 if (ret_val) 1254 if (ret_val)
@@ -2484,6 +2549,10 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
2484 if (!ret_val) 2549 if (!ret_val)
2485 e1000_release_swflag_ich8lan(hw); 2550 e1000_release_swflag_ich8lan(hw);
2486 2551
2552 /* Perform any necessary post-reset workarounds */
2553 if (hw->mac.type == e1000_pchlan)
2554 ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
2555
2487 if (ctrl & E1000_CTRL_PHY_RST) 2556 if (ctrl & E1000_CTRL_PHY_RST)
2488 ret_val = hw->phy.ops.get_cfg_done(hw); 2557 ret_val = hw->phy.ops.get_cfg_done(hw);
2489 2558
@@ -2528,9 +2597,6 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
2528 kab |= E1000_KABGTXD_BGSQLBIAS; 2597 kab |= E1000_KABGTXD_BGSQLBIAS;
2529 ew32(KABGTXD, kab); 2598 ew32(KABGTXD, kab);
2530 2599
2531 if (hw->mac.type == e1000_pchlan)
2532 ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
2533
2534out: 2600out:
2535 return ret_val; 2601 return ret_val;
2536} 2602}