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; |
