diff options
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r-- | drivers/net/skge.c | 357 |
1 files changed, 271 insertions, 86 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 9142d91355bc..705e9a8fa30f 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #define TX_WATCHDOG (5 * HZ) | 58 | #define TX_WATCHDOG (5 * HZ) |
59 | #define NAPI_WEIGHT 64 | 59 | #define NAPI_WEIGHT 64 |
60 | #define BLINK_MS 250 | 60 | #define BLINK_MS 250 |
61 | #define LINK_HZ (HZ/2) | ||
61 | 62 | ||
62 | MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); | 63 | MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); |
63 | MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>"); | 64 | MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>"); |
@@ -605,7 +606,12 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) | |||
605 | if (hw->chip_id == CHIP_ID_GENESIS) { | 606 | if (hw->chip_id == CHIP_ID_GENESIS) { |
606 | switch (mode) { | 607 | switch (mode) { |
607 | case LED_MODE_OFF: | 608 | case LED_MODE_OFF: |
608 | xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); | 609 | if (hw->phy_type == SK_PHY_BCOM) |
610 | xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); | ||
611 | else { | ||
612 | skge_write32(hw, SK_REG(port, TX_LED_VAL), 0); | ||
613 | skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_T_OFF); | ||
614 | } | ||
609 | skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); | 615 | skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); |
610 | skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); | 616 | skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); |
611 | skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); | 617 | skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); |
@@ -625,8 +631,14 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) | |||
625 | skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); | 631 | skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); |
626 | skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); | 632 | skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); |
627 | 633 | ||
628 | xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); | 634 | if (hw->phy_type == SK_PHY_BCOM) |
629 | break; | 635 | xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); |
636 | else { | ||
637 | skge_write8(hw, SK_REG(port, TX_LED_TST), LED_T_ON); | ||
638 | skge_write32(hw, SK_REG(port, TX_LED_VAL), 100); | ||
639 | skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); | ||
640 | } | ||
641 | |||
630 | } | 642 | } |
631 | } else { | 643 | } else { |
632 | switch (mode) { | 644 | switch (mode) { |
@@ -879,6 +891,9 @@ static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val) | |||
879 | xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); | 891 | xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); |
880 | *val = xm_read16(hw, port, XM_PHY_DATA); | 892 | *val = xm_read16(hw, port, XM_PHY_DATA); |
881 | 893 | ||
894 | if (hw->phy_type == SK_PHY_XMAC) | ||
895 | goto ready; | ||
896 | |||
882 | for (i = 0; i < PHY_RETRIES; i++) { | 897 | for (i = 0; i < PHY_RETRIES; i++) { |
883 | if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY) | 898 | if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY) |
884 | goto ready; | 899 | goto ready; |
@@ -965,7 +980,8 @@ static void genesis_reset(struct skge_hw *hw, int port) | |||
965 | xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */ | 980 | xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */ |
966 | 981 | ||
967 | /* disable Broadcom PHY IRQ */ | 982 | /* disable Broadcom PHY IRQ */ |
968 | xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff); | 983 | if (hw->phy_type == SK_PHY_BCOM) |
984 | xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff); | ||
969 | 985 | ||
970 | xm_outhash(hw, port, XM_HSM, zero); | 986 | xm_outhash(hw, port, XM_HSM, zero); |
971 | } | 987 | } |
@@ -1000,60 +1016,64 @@ static void bcom_check_link(struct skge_hw *hw, int port) | |||
1000 | 1016 | ||
1001 | if (netif_carrier_ok(dev)) | 1017 | if (netif_carrier_ok(dev)) |
1002 | skge_link_down(skge); | 1018 | skge_link_down(skge); |
1003 | } else { | 1019 | return; |
1004 | if (skge->autoneg == AUTONEG_ENABLE && | 1020 | } |
1005 | (status & PHY_ST_AN_OVER)) { | ||
1006 | u16 lpa = xm_phy_read(hw, port, PHY_BCOM_AUNE_LP); | ||
1007 | u16 aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT); | ||
1008 | |||
1009 | if (lpa & PHY_B_AN_RF) { | ||
1010 | printk(KERN_NOTICE PFX "%s: remote fault\n", | ||
1011 | dev->name); | ||
1012 | return; | ||
1013 | } | ||
1014 | 1021 | ||
1015 | /* Check Duplex mismatch */ | 1022 | if (skge->autoneg == AUTONEG_ENABLE) { |
1016 | switch (aux & PHY_B_AS_AN_RES_MSK) { | 1023 | u16 lpa, aux; |
1017 | case PHY_B_RES_1000FD: | ||
1018 | skge->duplex = DUPLEX_FULL; | ||
1019 | break; | ||
1020 | case PHY_B_RES_1000HD: | ||
1021 | skge->duplex = DUPLEX_HALF; | ||
1022 | break; | ||
1023 | default: | ||
1024 | printk(KERN_NOTICE PFX "%s: duplex mismatch\n", | ||
1025 | dev->name); | ||
1026 | return; | ||
1027 | } | ||
1028 | 1024 | ||
1025 | if (!(status & PHY_ST_AN_OVER)) | ||
1026 | return; | ||
1029 | 1027 | ||
1030 | /* We are using IEEE 802.3z/D5.0 Table 37-4 */ | 1028 | lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP); |
1031 | switch (aux & PHY_B_AS_PAUSE_MSK) { | 1029 | if (lpa & PHY_B_AN_RF) { |
1032 | case PHY_B_AS_PAUSE_MSK: | 1030 | printk(KERN_NOTICE PFX "%s: remote fault\n", |
1033 | skge->flow_control = FLOW_MODE_SYMMETRIC; | 1031 | dev->name); |
1034 | break; | 1032 | return; |
1035 | case PHY_B_AS_PRR: | 1033 | } |
1036 | skge->flow_control = FLOW_MODE_REM_SEND; | ||
1037 | break; | ||
1038 | case PHY_B_AS_PRT: | ||
1039 | skge->flow_control = FLOW_MODE_LOC_SEND; | ||
1040 | break; | ||
1041 | default: | ||
1042 | skge->flow_control = FLOW_MODE_NONE; | ||
1043 | } | ||
1044 | 1034 | ||
1045 | skge->speed = SPEED_1000; | 1035 | aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT); |
1036 | |||
1037 | /* Check Duplex mismatch */ | ||
1038 | switch (aux & PHY_B_AS_AN_RES_MSK) { | ||
1039 | case PHY_B_RES_1000FD: | ||
1040 | skge->duplex = DUPLEX_FULL; | ||
1041 | break; | ||
1042 | case PHY_B_RES_1000HD: | ||
1043 | skge->duplex = DUPLEX_HALF; | ||
1044 | break; | ||
1045 | default: | ||
1046 | printk(KERN_NOTICE PFX "%s: duplex mismatch\n", | ||
1047 | dev->name); | ||
1048 | return; | ||
1046 | } | 1049 | } |
1047 | 1050 | ||
1048 | if (!netif_carrier_ok(dev)) | 1051 | |
1049 | genesis_link_up(skge); | 1052 | /* We are using IEEE 802.3z/D5.0 Table 37-4 */ |
1053 | switch (aux & PHY_B_AS_PAUSE_MSK) { | ||
1054 | case PHY_B_AS_PAUSE_MSK: | ||
1055 | skge->flow_control = FLOW_MODE_SYMMETRIC; | ||
1056 | break; | ||
1057 | case PHY_B_AS_PRR: | ||
1058 | skge->flow_control = FLOW_MODE_REM_SEND; | ||
1059 | break; | ||
1060 | case PHY_B_AS_PRT: | ||
1061 | skge->flow_control = FLOW_MODE_LOC_SEND; | ||
1062 | break; | ||
1063 | default: | ||
1064 | skge->flow_control = FLOW_MODE_NONE; | ||
1065 | } | ||
1066 | skge->speed = SPEED_1000; | ||
1050 | } | 1067 | } |
1068 | |||
1069 | if (!netif_carrier_ok(dev)) | ||
1070 | genesis_link_up(skge); | ||
1051 | } | 1071 | } |
1052 | 1072 | ||
1053 | /* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional | 1073 | /* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional |
1054 | * Phy on for 100 or 10Mbit operation | 1074 | * Phy on for 100 or 10Mbit operation |
1055 | */ | 1075 | */ |
1056 | static void bcom_phy_init(struct skge_port *skge, int jumbo) | 1076 | static void bcom_phy_init(struct skge_port *skge) |
1057 | { | 1077 | { |
1058 | struct skge_hw *hw = skge->hw; | 1078 | struct skge_hw *hw = skge->hw; |
1059 | int port = skge->port; | 1079 | int port = skge->port; |
@@ -1144,7 +1164,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo) | |||
1144 | phy_pause_map[skge->flow_control] | PHY_AN_CSMA); | 1164 | phy_pause_map[skge->flow_control] | PHY_AN_CSMA); |
1145 | 1165 | ||
1146 | /* Handle Jumbo frames */ | 1166 | /* Handle Jumbo frames */ |
1147 | if (jumbo) { | 1167 | if (hw->dev[port]->mtu > ETH_DATA_LEN) { |
1148 | xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, | 1168 | xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, |
1149 | PHY_B_AC_TX_TST | PHY_B_AC_LONG_PACK); | 1169 | PHY_B_AC_TX_TST | PHY_B_AC_LONG_PACK); |
1150 | 1170 | ||
@@ -1157,8 +1177,154 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo) | |||
1157 | 1177 | ||
1158 | /* Use link status change interrupt */ | 1178 | /* Use link status change interrupt */ |
1159 | xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); | 1179 | xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); |
1180 | } | ||
1160 | 1181 | ||
1161 | bcom_check_link(hw, port); | 1182 | static void xm_phy_init(struct skge_port *skge) |
1183 | { | ||
1184 | struct skge_hw *hw = skge->hw; | ||
1185 | int port = skge->port; | ||
1186 | u16 ctrl = 0; | ||
1187 | |||
1188 | if (skge->autoneg == AUTONEG_ENABLE) { | ||
1189 | if (skge->advertising & ADVERTISED_1000baseT_Half) | ||
1190 | ctrl |= PHY_X_AN_HD; | ||
1191 | if (skge->advertising & ADVERTISED_1000baseT_Full) | ||
1192 | ctrl |= PHY_X_AN_FD; | ||
1193 | |||
1194 | switch(skge->flow_control) { | ||
1195 | case FLOW_MODE_NONE: | ||
1196 | ctrl |= PHY_X_P_NO_PAUSE; | ||
1197 | break; | ||
1198 | case FLOW_MODE_LOC_SEND: | ||
1199 | ctrl |= PHY_X_P_ASYM_MD; | ||
1200 | break; | ||
1201 | case FLOW_MODE_SYMMETRIC: | ||
1202 | ctrl |= PHY_X_P_BOTH_MD; | ||
1203 | break; | ||
1204 | } | ||
1205 | |||
1206 | xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl); | ||
1207 | |||
1208 | /* Restart Auto-negotiation */ | ||
1209 | ctrl = PHY_CT_ANE | PHY_CT_RE_CFG; | ||
1210 | } else { | ||
1211 | /* Set DuplexMode in Config register */ | ||
1212 | if (skge->duplex == DUPLEX_FULL) | ||
1213 | ctrl |= PHY_CT_DUP_MD; | ||
1214 | /* | ||
1215 | * Do NOT enable Auto-negotiation here. This would hold | ||
1216 | * the link down because no IDLEs are transmitted | ||
1217 | */ | ||
1218 | } | ||
1219 | |||
1220 | xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl); | ||
1221 | |||
1222 | /* Poll PHY for status changes */ | ||
1223 | schedule_delayed_work(&skge->link_thread, LINK_HZ); | ||
1224 | } | ||
1225 | |||
1226 | static void xm_check_link(struct net_device *dev) | ||
1227 | { | ||
1228 | struct skge_port *skge = netdev_priv(dev); | ||
1229 | struct skge_hw *hw = skge->hw; | ||
1230 | int port = skge->port; | ||
1231 | u16 status; | ||
1232 | |||
1233 | /* read twice because of latch */ | ||
1234 | (void) xm_phy_read(hw, port, PHY_XMAC_STAT); | ||
1235 | status = xm_phy_read(hw, port, PHY_XMAC_STAT); | ||
1236 | |||
1237 | if ((status & PHY_ST_LSYNC) == 0) { | ||
1238 | u16 cmd = xm_read16(hw, port, XM_MMU_CMD); | ||
1239 | cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); | ||
1240 | xm_write16(hw, port, XM_MMU_CMD, cmd); | ||
1241 | /* dummy read to ensure writing */ | ||
1242 | (void) xm_read16(hw, port, XM_MMU_CMD); | ||
1243 | |||
1244 | if (netif_carrier_ok(dev)) | ||
1245 | skge_link_down(skge); | ||
1246 | return; | ||
1247 | } | ||
1248 | |||
1249 | if (skge->autoneg == AUTONEG_ENABLE) { | ||
1250 | u16 lpa, res; | ||
1251 | |||
1252 | if (!(status & PHY_ST_AN_OVER)) | ||
1253 | return; | ||
1254 | |||
1255 | lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP); | ||
1256 | if (lpa & PHY_B_AN_RF) { | ||
1257 | printk(KERN_NOTICE PFX "%s: remote fault\n", | ||
1258 | dev->name); | ||
1259 | return; | ||
1260 | } | ||
1261 | |||
1262 | res = xm_phy_read(hw, port, PHY_XMAC_RES_ABI); | ||
1263 | |||
1264 | /* Check Duplex mismatch */ | ||
1265 | switch (res & (PHY_X_RS_HD | PHY_X_RS_FD)) { | ||
1266 | case PHY_X_RS_FD: | ||
1267 | skge->duplex = DUPLEX_FULL; | ||
1268 | break; | ||
1269 | case PHY_X_RS_HD: | ||
1270 | skge->duplex = DUPLEX_HALF; | ||
1271 | break; | ||
1272 | default: | ||
1273 | printk(KERN_NOTICE PFX "%s: duplex mismatch\n", | ||
1274 | dev->name); | ||
1275 | return; | ||
1276 | } | ||
1277 | |||
1278 | /* We are using IEEE 802.3z/D5.0 Table 37-4 */ | ||
1279 | if (lpa & PHY_X_P_SYM_MD) | ||
1280 | skge->flow_control = FLOW_MODE_SYMMETRIC; | ||
1281 | else if ((lpa & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) | ||
1282 | skge->flow_control = FLOW_MODE_REM_SEND; | ||
1283 | else if ((lpa & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) | ||
1284 | skge->flow_control = FLOW_MODE_LOC_SEND; | ||
1285 | else | ||
1286 | skge->flow_control = FLOW_MODE_NONE; | ||
1287 | |||
1288 | |||
1289 | skge->speed = SPEED_1000; | ||
1290 | } | ||
1291 | |||
1292 | if (!netif_carrier_ok(dev)) | ||
1293 | genesis_link_up(skge); | ||
1294 | } | ||
1295 | |||
1296 | /* Poll to check for link coming up. | ||
1297 | * Since internal PHY is wired to a level triggered pin, can't | ||
1298 | * get an interrupt when carrier is detected. | ||
1299 | */ | ||
1300 | static void xm_link_timer(void *arg) | ||
1301 | { | ||
1302 | struct net_device *dev = arg; | ||
1303 | struct skge_port *skge = netdev_priv(arg); | ||
1304 | struct skge_hw *hw = skge->hw; | ||
1305 | int port = skge->port; | ||
1306 | |||
1307 | if (!netif_running(dev)) | ||
1308 | return; | ||
1309 | |||
1310 | if (netif_carrier_ok(dev)) { | ||
1311 | xm_read16(hw, port, XM_ISRC); | ||
1312 | if (!(xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS)) | ||
1313 | goto nochange; | ||
1314 | } else { | ||
1315 | if (xm_read32(hw, port, XM_GP_PORT) & XM_GP_INP_ASS) | ||
1316 | goto nochange; | ||
1317 | xm_read16(hw, port, XM_ISRC); | ||
1318 | if (xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS) | ||
1319 | goto nochange; | ||
1320 | } | ||
1321 | |||
1322 | mutex_lock(&hw->phy_mutex); | ||
1323 | xm_check_link(dev); | ||
1324 | mutex_unlock(&hw->phy_mutex); | ||
1325 | |||
1326 | nochange: | ||
1327 | schedule_delayed_work(&skge->link_thread, LINK_HZ); | ||
1162 | } | 1328 | } |
1163 | 1329 | ||
1164 | static void genesis_mac_init(struct skge_hw *hw, int port) | 1330 | static void genesis_mac_init(struct skge_hw *hw, int port) |
@@ -1189,20 +1355,29 @@ static void genesis_mac_init(struct skge_hw *hw, int port) | |||
1189 | * namely for the 1000baseTX cards that use the XMAC's | 1355 | * namely for the 1000baseTX cards that use the XMAC's |
1190 | * GMII mode. | 1356 | * GMII mode. |
1191 | */ | 1357 | */ |
1192 | /* Take external Phy out of reset */ | 1358 | if (hw->phy_type != SK_PHY_XMAC) { |
1193 | r = skge_read32(hw, B2_GP_IO); | 1359 | /* Take external Phy out of reset */ |
1194 | if (port == 0) | 1360 | r = skge_read32(hw, B2_GP_IO); |
1195 | r |= GP_DIR_0|GP_IO_0; | 1361 | if (port == 0) |
1196 | else | 1362 | r |= GP_DIR_0|GP_IO_0; |
1197 | r |= GP_DIR_2|GP_IO_2; | 1363 | else |
1364 | r |= GP_DIR_2|GP_IO_2; | ||
1198 | 1365 | ||
1199 | skge_write32(hw, B2_GP_IO, r); | 1366 | skge_write32(hw, B2_GP_IO, r); |
1200 | 1367 | ||
1368 | /* Enable GMII interface */ | ||
1369 | xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); | ||
1370 | } | ||
1201 | 1371 | ||
1202 | /* Enable GMII interface */ | ||
1203 | xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); | ||
1204 | 1372 | ||
1205 | bcom_phy_init(skge, jumbo); | 1373 | switch(hw->phy_type) { |
1374 | case SK_PHY_XMAC: | ||
1375 | xm_phy_init(skge); | ||
1376 | break; | ||
1377 | case SK_PHY_BCOM: | ||
1378 | bcom_phy_init(skge); | ||
1379 | bcom_check_link(hw, port); | ||
1380 | } | ||
1206 | 1381 | ||
1207 | /* Set Station Address */ | 1382 | /* Set Station Address */ |
1208 | xm_outaddr(hw, port, XM_SA, dev->dev_addr); | 1383 | xm_outaddr(hw, port, XM_SA, dev->dev_addr); |
@@ -1335,16 +1510,18 @@ static void genesis_stop(struct skge_port *skge) | |||
1335 | skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST); | 1510 | skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST); |
1336 | 1511 | ||
1337 | /* For external PHYs there must be special handling */ | 1512 | /* For external PHYs there must be special handling */ |
1338 | reg = skge_read32(hw, B2_GP_IO); | 1513 | if (hw->phy_type != SK_PHY_XMAC) { |
1339 | if (port == 0) { | 1514 | reg = skge_read32(hw, B2_GP_IO); |
1340 | reg |= GP_DIR_0; | 1515 | if (port == 0) { |
1341 | reg &= ~GP_IO_0; | 1516 | reg |= GP_DIR_0; |
1342 | } else { | 1517 | reg &= ~GP_IO_0; |
1343 | reg |= GP_DIR_2; | 1518 | } else { |
1344 | reg &= ~GP_IO_2; | 1519 | reg |= GP_DIR_2; |
1520 | reg &= ~GP_IO_2; | ||
1521 | } | ||
1522 | skge_write32(hw, B2_GP_IO, reg); | ||
1523 | skge_read32(hw, B2_GP_IO); | ||
1345 | } | 1524 | } |
1346 | skge_write32(hw, B2_GP_IO, reg); | ||
1347 | skge_read32(hw, B2_GP_IO); | ||
1348 | 1525 | ||
1349 | xm_write16(hw, port, XM_MMU_CMD, | 1526 | xm_write16(hw, port, XM_MMU_CMD, |
1350 | xm_read16(hw, port, XM_MMU_CMD) | 1527 | xm_read16(hw, port, XM_MMU_CMD) |
@@ -1406,7 +1583,7 @@ static void genesis_link_up(struct skge_port *skge) | |||
1406 | struct skge_hw *hw = skge->hw; | 1583 | struct skge_hw *hw = skge->hw; |
1407 | int port = skge->port; | 1584 | int port = skge->port; |
1408 | u16 cmd; | 1585 | u16 cmd; |
1409 | u32 mode, msk; | 1586 | u32 mode; |
1410 | 1587 | ||
1411 | cmd = xm_read16(hw, port, XM_MMU_CMD); | 1588 | cmd = xm_read16(hw, port, XM_MMU_CMD); |
1412 | 1589 | ||
@@ -1454,27 +1631,24 @@ static void genesis_link_up(struct skge_port *skge) | |||
1454 | } | 1631 | } |
1455 | 1632 | ||
1456 | xm_write32(hw, port, XM_MODE, mode); | 1633 | xm_write32(hw, port, XM_MODE, mode); |
1457 | 1634 | xm_write16(hw, port, XM_IMSK, XM_DEF_MSK); | |
1458 | msk = XM_DEF_MSK; | ||
1459 | /* disable GP0 interrupt bit for external Phy */ | ||
1460 | msk |= XM_IS_INP_ASS; | ||
1461 | |||
1462 | xm_write16(hw, port, XM_IMSK, msk); | ||
1463 | xm_read16(hw, port, XM_ISRC); | 1635 | xm_read16(hw, port, XM_ISRC); |
1464 | 1636 | ||
1465 | /* get MMU Command Reg. */ | 1637 | /* get MMU Command Reg. */ |
1466 | cmd = xm_read16(hw, port, XM_MMU_CMD); | 1638 | cmd = xm_read16(hw, port, XM_MMU_CMD); |
1467 | if (skge->duplex == DUPLEX_FULL) | 1639 | if (hw->phy_type != SK_PHY_XMAC && skge->duplex == DUPLEX_FULL) |
1468 | cmd |= XM_MMU_GMII_FD; | 1640 | cmd |= XM_MMU_GMII_FD; |
1469 | 1641 | ||
1470 | /* | 1642 | /* |
1471 | * Workaround BCOM Errata (#10523) for all BCom Phys | 1643 | * Workaround BCOM Errata (#10523) for all BCom Phys |
1472 | * Enable Power Management after link up | 1644 | * Enable Power Management after link up |
1473 | */ | 1645 | */ |
1474 | xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, | 1646 | if (hw->phy_type == SK_PHY_BCOM) { |
1475 | xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL) | 1647 | xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, |
1476 | & ~PHY_B_AC_DIS_PM); | 1648 | xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL) |
1477 | xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); | 1649 | & ~PHY_B_AC_DIS_PM); |
1650 | xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); | ||
1651 | } | ||
1478 | 1652 | ||
1479 | /* enable Rx/Tx */ | 1653 | /* enable Rx/Tx */ |
1480 | xm_write16(hw, port, XM_MMU_CMD, | 1654 | xm_write16(hw, port, XM_MMU_CMD, |
@@ -2240,6 +2414,8 @@ static int skge_down(struct net_device *dev) | |||
2240 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); | 2414 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); |
2241 | 2415 | ||
2242 | netif_stop_queue(dev); | 2416 | netif_stop_queue(dev); |
2417 | if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC) | ||
2418 | cancel_rearming_delayed_work(&skge->link_thread); | ||
2243 | 2419 | ||
2244 | skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); | 2420 | skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); |
2245 | if (hw->chip_id == CHIP_ID_GENESIS) | 2421 | if (hw->chip_id == CHIP_ID_GENESIS) |
@@ -2862,7 +3038,7 @@ static void skge_extirq(void *arg) | |||
2862 | if (netif_running(dev)) { | 3038 | if (netif_running(dev)) { |
2863 | if (hw->chip_id != CHIP_ID_GENESIS) | 3039 | if (hw->chip_id != CHIP_ID_GENESIS) |
2864 | yukon_phy_intr(skge); | 3040 | yukon_phy_intr(skge); |
2865 | else | 3041 | else if (hw->phy_type == SK_PHY_BCOM) |
2866 | bcom_phy_intr(skge); | 3042 | bcom_phy_intr(skge); |
2867 | } | 3043 | } |
2868 | } | 3044 | } |
@@ -3014,7 +3190,7 @@ static int skge_reset(struct skge_hw *hw) | |||
3014 | { | 3190 | { |
3015 | u32 reg; | 3191 | u32 reg; |
3016 | u16 ctst, pci_status; | 3192 | u16 ctst, pci_status; |
3017 | u8 t8, mac_cfg, pmd_type, phy_type; | 3193 | u8 t8, mac_cfg, pmd_type; |
3018 | int i; | 3194 | int i; |
3019 | 3195 | ||
3020 | ctst = skge_read16(hw, B0_CTST); | 3196 | ctst = skge_read16(hw, B0_CTST); |
@@ -3038,19 +3214,22 @@ static int skge_reset(struct skge_hw *hw) | |||
3038 | ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA)); | 3214 | ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA)); |
3039 | 3215 | ||
3040 | hw->chip_id = skge_read8(hw, B2_CHIP_ID); | 3216 | hw->chip_id = skge_read8(hw, B2_CHIP_ID); |
3041 | phy_type = skge_read8(hw, B2_E_1) & 0xf; | 3217 | hw->phy_type = skge_read8(hw, B2_E_1) & 0xf; |
3042 | pmd_type = skge_read8(hw, B2_PMD_TYP); | 3218 | pmd_type = skge_read8(hw, B2_PMD_TYP); |
3043 | hw->copper = (pmd_type == 'T' || pmd_type == '1'); | 3219 | hw->copper = (pmd_type == 'T' || pmd_type == '1'); |
3044 | 3220 | ||
3045 | switch (hw->chip_id) { | 3221 | switch (hw->chip_id) { |
3046 | case CHIP_ID_GENESIS: | 3222 | case CHIP_ID_GENESIS: |
3047 | switch (phy_type) { | 3223 | switch (hw->phy_type) { |
3224 | case SK_PHY_XMAC: | ||
3225 | hw->phy_addr = PHY_ADDR_XMAC; | ||
3226 | break; | ||
3048 | case SK_PHY_BCOM: | 3227 | case SK_PHY_BCOM: |
3049 | hw->phy_addr = PHY_ADDR_BCOM; | 3228 | hw->phy_addr = PHY_ADDR_BCOM; |
3050 | break; | 3229 | break; |
3051 | default: | 3230 | default: |
3052 | printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n", | 3231 | printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n", |
3053 | pci_name(hw->pdev), phy_type); | 3232 | pci_name(hw->pdev), hw->phy_type); |
3054 | return -EOPNOTSUPP; | 3233 | return -EOPNOTSUPP; |
3055 | } | 3234 | } |
3056 | break; | 3235 | break; |
@@ -3058,7 +3237,7 @@ static int skge_reset(struct skge_hw *hw) | |||
3058 | case CHIP_ID_YUKON: | 3237 | case CHIP_ID_YUKON: |
3059 | case CHIP_ID_YUKON_LITE: | 3238 | case CHIP_ID_YUKON_LITE: |
3060 | case CHIP_ID_YUKON_LP: | 3239 | case CHIP_ID_YUKON_LP: |
3061 | if (phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S') | 3240 | if (hw->phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S') |
3062 | hw->copper = 1; | 3241 | hw->copper = 1; |
3063 | 3242 | ||
3064 | hw->phy_addr = PHY_ADDR_MARV; | 3243 | hw->phy_addr = PHY_ADDR_MARV; |
@@ -3089,10 +3268,13 @@ static int skge_reset(struct skge_hw *hw) | |||
3089 | else | 3268 | else |
3090 | hw->ram_size = t8 * 4096; | 3269 | hw->ram_size = t8 * 4096; |
3091 | 3270 | ||
3092 | hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1; | 3271 | hw->intr_mask = IS_HW_ERR | IS_PORT_1; |
3093 | if (hw->ports > 1) | 3272 | if (hw->ports > 1) |
3094 | hw->intr_mask |= IS_PORT_2; | 3273 | hw->intr_mask |= IS_PORT_2; |
3095 | 3274 | ||
3275 | if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)) | ||
3276 | hw->intr_mask |= IS_EXT_REG; | ||
3277 | |||
3096 | if (hw->chip_id == CHIP_ID_GENESIS) | 3278 | if (hw->chip_id == CHIP_ID_GENESIS) |
3097 | genesis_init(hw); | 3279 | genesis_init(hw); |
3098 | else { | 3280 | else { |
@@ -3226,6 +3408,9 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, | |||
3226 | 3408 | ||
3227 | skge->port = port; | 3409 | skge->port = port; |
3228 | 3410 | ||
3411 | /* Only used for Genesis XMAC */ | ||
3412 | INIT_WORK(&skge->link_thread, xm_link_timer, dev); | ||
3413 | |||
3229 | if (hw->chip_id != CHIP_ID_GENESIS) { | 3414 | if (hw->chip_id != CHIP_ID_GENESIS) { |
3230 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; | 3415 | dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; |
3231 | skge->rx_csum = 1; | 3416 | skge->rx_csum = 1; |