diff options
author | Bruce Allan <bruce.w.allan@intel.com> | 2008-11-21 19:53:51 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-21 19:53:51 -0500 |
commit | 75eb0fad56da8494b43865097f362633debdc958 (patch) | |
tree | a0c0b5ba3ad92712b52d934d911ebb69eee254bf /drivers/net/e1000e/es2lan.c | |
parent | 438b365a2758c012393a7be24d31a9c06aa0a504 (diff) |
e1000e: ESB2 config after link up
On ESB2, the MAC-to-PHY (Kumeran) interface must be configured after link
is up before any traffic is sent; a new PHY operations function pointer is
provided for this. To facilitate read/write of the Kumeran registers
without blocking PHY register writes, the driver/firmware synchronization
method which previously used a hardware semaphore for both PHY and Kumeran
register accesses is now split. New Kumeran register read/write functions
utilize this new synchronization method.
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/e1000e/es2lan.c')
-rw-r--r-- | drivers/net/e1000e/es2lan.c | 192 |
1 files changed, 155 insertions, 37 deletions
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c index da9c09c248ed..db51114ebfde 100644 --- a/drivers/net/e1000e/es2lan.c +++ b/drivers/net/e1000e/es2lan.c | |||
@@ -112,6 +112,11 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw); | |||
112 | static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw); | 112 | static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw); |
113 | static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw); | 113 | static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw); |
114 | static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex); | 114 | static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex); |
115 | static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw); | ||
116 | static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, | ||
117 | u16 *data); | ||
118 | static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, | ||
119 | u16 data); | ||
115 | 120 | ||
116 | /** | 121 | /** |
117 | * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs. | 122 | * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs. |
@@ -275,8 +280,6 @@ static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw) | |||
275 | u16 mask; | 280 | u16 mask; |
276 | 281 | ||
277 | mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; | 282 | mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; |
278 | mask |= E1000_SWFW_CSR_SM; | ||
279 | |||
280 | return e1000_acquire_swfw_sync_80003es2lan(hw, mask); | 283 | return e1000_acquire_swfw_sync_80003es2lan(hw, mask); |
281 | } | 284 | } |
282 | 285 | ||
@@ -292,7 +295,36 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw) | |||
292 | u16 mask; | 295 | u16 mask; |
293 | 296 | ||
294 | mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; | 297 | mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; |
295 | mask |= E1000_SWFW_CSR_SM; | 298 | e1000_release_swfw_sync_80003es2lan(hw, mask); |
299 | } | ||
300 | |||
301 | /** | ||
302 | * e1000_acquire_mac_csr_80003es2lan - Acquire rights to access Kumeran register | ||
303 | * @hw: pointer to the HW structure | ||
304 | * | ||
305 | * Acquire the semaphore to access the Kumeran interface. | ||
306 | * | ||
307 | **/ | ||
308 | static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw) | ||
309 | { | ||
310 | u16 mask; | ||
311 | |||
312 | mask = E1000_SWFW_CSR_SM; | ||
313 | |||
314 | return e1000_acquire_swfw_sync_80003es2lan(hw, mask); | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * e1000_release_mac_csr_80003es2lan - Release rights to access Kumeran Register | ||
319 | * @hw: pointer to the HW structure | ||
320 | * | ||
321 | * Release the semaphore used to access the Kumeran interface | ||
322 | **/ | ||
323 | static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw) | ||
324 | { | ||
325 | u16 mask; | ||
326 | |||
327 | mask = E1000_SWFW_CSR_SM; | ||
296 | 328 | ||
297 | e1000_release_swfw_sync_80003es2lan(hw, mask); | 329 | e1000_release_swfw_sync_80003es2lan(hw, mask); |
298 | } | 330 | } |
@@ -347,7 +379,7 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) | |||
347 | u32 swmask = mask; | 379 | u32 swmask = mask; |
348 | u32 fwmask = mask << 16; | 380 | u32 fwmask = mask << 16; |
349 | s32 i = 0; | 381 | s32 i = 0; |
350 | s32 timeout = 200; | 382 | s32 timeout = 50; |
351 | 383 | ||
352 | while (i < timeout) { | 384 | while (i < timeout) { |
353 | if (e1000e_get_hw_semaphore(hw)) | 385 | if (e1000e_get_hw_semaphore(hw)) |
@@ -715,13 +747,7 @@ static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, | |||
715 | ret_val = e1000e_get_speed_and_duplex_copper(hw, | 747 | ret_val = e1000e_get_speed_and_duplex_copper(hw, |
716 | speed, | 748 | speed, |
717 | duplex); | 749 | duplex); |
718 | if (ret_val) | 750 | hw->phy.ops.cfg_on_link_up(hw); |
719 | return ret_val; | ||
720 | if (*speed == SPEED_1000) | ||
721 | ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw); | ||
722 | else | ||
723 | ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, | ||
724 | *duplex); | ||
725 | } else { | 751 | } else { |
726 | ret_val = e1000e_get_speed_and_duplex_fiber_serdes(hw, | 752 | ret_val = e1000e_get_speed_and_duplex_fiber_serdes(hw, |
727 | speed, | 753 | speed, |
@@ -763,8 +789,10 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) | |||
763 | 789 | ||
764 | ctrl = er32(CTRL); | 790 | ctrl = er32(CTRL); |
765 | 791 | ||
792 | ret_val = e1000_acquire_phy_80003es2lan(hw); | ||
766 | hw_dbg(hw, "Issuing a global reset to MAC\n"); | 793 | hw_dbg(hw, "Issuing a global reset to MAC\n"); |
767 | ew32(CTRL, ctrl | E1000_CTRL_RST); | 794 | ew32(CTRL, ctrl | E1000_CTRL_RST); |
795 | e1000_release_phy_80003es2lan(hw); | ||
768 | 796 | ||
769 | ret_val = e1000e_get_auto_rd_done(hw); | 797 | ret_val = e1000e_get_auto_rd_done(hw); |
770 | if (ret_val) | 798 | if (ret_val) |
@@ -907,8 +935,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) | |||
907 | struct e1000_phy_info *phy = &hw->phy; | 935 | struct e1000_phy_info *phy = &hw->phy; |
908 | s32 ret_val; | 936 | s32 ret_val; |
909 | u32 ctrl_ext; | 937 | u32 ctrl_ext; |
910 | u32 i = 0; | 938 | u16 data; |
911 | u16 data, data2; | ||
912 | 939 | ||
913 | ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data); | 940 | ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data); |
914 | if (ret_val) | 941 | if (ret_val) |
@@ -972,19 +999,20 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) | |||
972 | } | 999 | } |
973 | 1000 | ||
974 | /* Bypass Rx and Tx FIFO's */ | 1001 | /* Bypass Rx and Tx FIFO's */ |
975 | ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL, | 1002 | ret_val = e1000_write_kmrn_reg_80003es2lan(hw, |
1003 | E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL, | ||
976 | E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | | 1004 | E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | |
977 | E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); | 1005 | E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); |
978 | if (ret_val) | 1006 | if (ret_val) |
979 | return ret_val; | 1007 | return ret_val; |
980 | 1008 | ||
981 | ret_val = e1000e_read_kmrn_reg(hw, | 1009 | ret_val = e1000_read_kmrn_reg_80003es2lan(hw, |
982 | E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, | 1010 | E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, |
983 | &data); | 1011 | &data); |
984 | if (ret_val) | 1012 | if (ret_val) |
985 | return ret_val; | 1013 | return ret_val; |
986 | data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE; | 1014 | data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE; |
987 | ret_val = e1000e_write_kmrn_reg(hw, | 1015 | ret_val = e1000_write_kmrn_reg_80003es2lan(hw, |
988 | E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, | 1016 | E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, |
989 | data); | 1017 | data); |
990 | if (ret_val) | 1018 | if (ret_val) |
@@ -1019,18 +1047,9 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) | |||
1019 | if (ret_val) | 1047 | if (ret_val) |
1020 | return ret_val; | 1048 | return ret_val; |
1021 | 1049 | ||
1022 | do { | 1050 | ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &data); |
1023 | ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, | 1051 | if (ret_val) |
1024 | &data); | 1052 | return ret_val; |
1025 | if (ret_val) | ||
1026 | return ret_val; | ||
1027 | |||
1028 | ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, | ||
1029 | &data2); | ||
1030 | if (ret_val) | ||
1031 | return ret_val; | ||
1032 | i++; | ||
1033 | } while ((data != data2) && (i < GG82563_MAX_KMRN_RETRY)); | ||
1034 | 1053 | ||
1035 | data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; | 1054 | data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; |
1036 | ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, data); | 1055 | ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, data); |
@@ -1077,23 +1096,27 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw) | |||
1077 | * iteration and increase the max iterations when | 1096 | * iteration and increase the max iterations when |
1078 | * polling the phy; this fixes erroneous timeouts at 10Mbps. | 1097 | * polling the phy; this fixes erroneous timeouts at 10Mbps. |
1079 | */ | 1098 | */ |
1080 | ret_val = e1000e_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF); | 1099 | ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4), |
1100 | 0xFFFF); | ||
1081 | if (ret_val) | 1101 | if (ret_val) |
1082 | return ret_val; | 1102 | return ret_val; |
1083 | ret_val = e1000e_read_kmrn_reg(hw, GG82563_REG(0x34, 9), ®_data); | 1103 | ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), |
1104 | ®_data); | ||
1084 | if (ret_val) | 1105 | if (ret_val) |
1085 | return ret_val; | 1106 | return ret_val; |
1086 | reg_data |= 0x3F; | 1107 | reg_data |= 0x3F; |
1087 | ret_val = e1000e_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data); | 1108 | ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), |
1109 | reg_data); | ||
1088 | if (ret_val) | 1110 | if (ret_val) |
1089 | return ret_val; | 1111 | return ret_val; |
1090 | ret_val = e1000e_read_kmrn_reg(hw, | 1112 | ret_val = e1000_read_kmrn_reg_80003es2lan(hw, |
1091 | E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, | 1113 | E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, |
1092 | ®_data); | 1114 | ®_data); |
1093 | if (ret_val) | 1115 | if (ret_val) |
1094 | return ret_val; | 1116 | return ret_val; |
1095 | reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING; | 1117 | reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING; |
1096 | ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, | 1118 | ret_val = e1000_write_kmrn_reg_80003es2lan(hw, |
1119 | E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, | ||
1097 | reg_data); | 1120 | reg_data); |
1098 | if (ret_val) | 1121 | if (ret_val) |
1099 | return ret_val; | 1122 | return ret_val; |
@@ -1108,6 +1131,35 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw) | |||
1108 | } | 1131 | } |
1109 | 1132 | ||
1110 | /** | 1133 | /** |
1134 | * e1000_cfg_on_link_up_80003es2lan - es2 link configuration after link-up | ||
1135 | * @hw: pointer to the HW structure | ||
1136 | * @duplex: current duplex setting | ||
1137 | * | ||
1138 | * Configure the KMRN interface by applying last minute quirks for | ||
1139 | * 10/100 operation. | ||
1140 | **/ | ||
1141 | static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw) | ||
1142 | { | ||
1143 | s32 ret_val = 0; | ||
1144 | u16 speed; | ||
1145 | u16 duplex; | ||
1146 | |||
1147 | if (hw->phy.media_type == e1000_media_type_copper) { | ||
1148 | ret_val = e1000e_get_speed_and_duplex_copper(hw, &speed, | ||
1149 | &duplex); | ||
1150 | if (ret_val) | ||
1151 | return ret_val; | ||
1152 | |||
1153 | if (speed == SPEED_1000) | ||
1154 | ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw); | ||
1155 | else | ||
1156 | ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex); | ||
1157 | } | ||
1158 | |||
1159 | return ret_val; | ||
1160 | } | ||
1161 | |||
1162 | /** | ||
1111 | * e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation | 1163 | * e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation |
1112 | * @hw: pointer to the HW structure | 1164 | * @hw: pointer to the HW structure |
1113 | * @duplex: current duplex setting | 1165 | * @duplex: current duplex setting |
@@ -1123,8 +1175,9 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) | |||
1123 | u16 reg_data, reg_data2; | 1175 | u16 reg_data, reg_data2; |
1124 | 1176 | ||
1125 | reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; | 1177 | reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; |
1126 | ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, | 1178 | ret_val = e1000_write_kmrn_reg_80003es2lan(hw, |
1127 | reg_data); | 1179 | E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, |
1180 | reg_data); | ||
1128 | if (ret_val) | 1181 | if (ret_val) |
1129 | return ret_val; | 1182 | return ret_val; |
1130 | 1183 | ||
@@ -1170,8 +1223,9 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) | |||
1170 | u32 i = 0; | 1223 | u32 i = 0; |
1171 | 1224 | ||
1172 | reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; | 1225 | reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; |
1173 | ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, | 1226 | ret_val = e1000_write_kmrn_reg_80003es2lan(hw, |
1174 | reg_data); | 1227 | E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, |
1228 | reg_data); | ||
1175 | if (ret_val) | 1229 | if (ret_val) |
1176 | return ret_val; | 1230 | return ret_val; |
1177 | 1231 | ||
@@ -1199,6 +1253,69 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) | |||
1199 | } | 1253 | } |
1200 | 1254 | ||
1201 | /** | 1255 | /** |
1256 | * e1000_read_kmrn_reg_80003es2lan - Read kumeran register | ||
1257 | * @hw: pointer to the HW structure | ||
1258 | * @offset: register offset to be read | ||
1259 | * @data: pointer to the read data | ||
1260 | * | ||
1261 | * Acquire semaphore, then read the PHY register at offset | ||
1262 | * using the kumeran interface. The information retrieved is stored in data. | ||
1263 | * Release the semaphore before exiting. | ||
1264 | **/ | ||
1265 | s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data) | ||
1266 | { | ||
1267 | u32 kmrnctrlsta; | ||
1268 | s32 ret_val = 0; | ||
1269 | |||
1270 | ret_val = e1000_acquire_mac_csr_80003es2lan(hw); | ||
1271 | if (ret_val) | ||
1272 | return ret_val; | ||
1273 | |||
1274 | kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & | ||
1275 | E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; | ||
1276 | ew32(KMRNCTRLSTA, kmrnctrlsta); | ||
1277 | |||
1278 | udelay(2); | ||
1279 | |||
1280 | kmrnctrlsta = er32(KMRNCTRLSTA); | ||
1281 | *data = (u16)kmrnctrlsta; | ||
1282 | |||
1283 | e1000_release_mac_csr_80003es2lan(hw); | ||
1284 | |||
1285 | return ret_val; | ||
1286 | } | ||
1287 | |||
1288 | /** | ||
1289 | * e1000_write_kmrn_reg_80003es2lan - Write kumeran register | ||
1290 | * @hw: pointer to the HW structure | ||
1291 | * @offset: register offset to write to | ||
1292 | * @data: data to write at register offset | ||
1293 | * | ||
1294 | * Acquire semaphore, then write the data to PHY register | ||
1295 | * at the offset using the kumeran interface. Release semaphore | ||
1296 | * before exiting. | ||
1297 | **/ | ||
1298 | s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data) | ||
1299 | { | ||
1300 | u32 kmrnctrlsta; | ||
1301 | s32 ret_val = 0; | ||
1302 | |||
1303 | ret_val = e1000_acquire_mac_csr_80003es2lan(hw); | ||
1304 | if (ret_val) | ||
1305 | return ret_val; | ||
1306 | |||
1307 | kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & | ||
1308 | E1000_KMRNCTRLSTA_OFFSET) | data; | ||
1309 | ew32(KMRNCTRLSTA, kmrnctrlsta); | ||
1310 | |||
1311 | udelay(2); | ||
1312 | |||
1313 | e1000_release_mac_csr_80003es2lan(hw); | ||
1314 | |||
1315 | return ret_val; | ||
1316 | } | ||
1317 | |||
1318 | /** | ||
1202 | * e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters | 1319 | * e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters |
1203 | * @hw: pointer to the HW structure | 1320 | * @hw: pointer to the HW structure |
1204 | * | 1321 | * |
@@ -1276,6 +1393,7 @@ static struct e1000_phy_operations es2_phy_ops = { | |||
1276 | .set_d0_lplu_state = NULL, | 1393 | .set_d0_lplu_state = NULL, |
1277 | .set_d3_lplu_state = e1000e_set_d3_lplu_state, | 1394 | .set_d3_lplu_state = e1000e_set_d3_lplu_state, |
1278 | .write_phy_reg = e1000_write_phy_reg_gg82563_80003es2lan, | 1395 | .write_phy_reg = e1000_write_phy_reg_gg82563_80003es2lan, |
1396 | .cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan, | ||
1279 | }; | 1397 | }; |
1280 | 1398 | ||
1281 | static struct e1000_nvm_operations es2_nvm_ops = { | 1399 | static struct e1000_nvm_operations es2_nvm_ops = { |