diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2005-06-27 14:33:12 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-06-27 18:05:06 -0400 |
commit | 45bada65c2a0bcc00729646071e66042ced64998 (patch) | |
tree | 91cc168686042f41149ea782ae91e8f8276b4402 /drivers | |
parent | 31b619c5abaa5512e7b41f190f9b7903b902f29a (diff) |
[PATCH] skge: make Genesis/Broadcom code work
Rewrite the code for handling the Broadcom PHY to something that
works. Remove link polling because Broadcom and Yukon don't need it.
When I wrote initial code, didn't have a genesis chipset based
board to test, so it was a non-working guess.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/skge.c | 516 | ||||
-rw-r--r-- | drivers/net/skge.h | 15 |
2 files changed, 274 insertions, 257 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 81b8fe9581c7..f11e0e1a3d0e 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -54,7 +54,6 @@ | |||
54 | #define TX_WATCHDOG (5 * HZ) | 54 | #define TX_WATCHDOG (5 * HZ) |
55 | #define NAPI_WEIGHT 64 | 55 | #define NAPI_WEIGHT 64 |
56 | #define BLINK_HZ (HZ/4) | 56 | #define BLINK_HZ (HZ/4) |
57 | #define LINK_POLL_HZ (HZ/10) | ||
58 | 57 | ||
59 | MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); | 58 | MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); |
60 | MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>"); | 59 | MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>"); |
@@ -96,6 +95,7 @@ static void yukon_init(struct skge_hw *hw, int port); | |||
96 | static void yukon_reset(struct skge_hw *hw, int port); | 95 | static void yukon_reset(struct skge_hw *hw, int port); |
97 | static void genesis_mac_init(struct skge_hw *hw, int port); | 96 | static void genesis_mac_init(struct skge_hw *hw, int port); |
98 | static void genesis_reset(struct skge_hw *hw, int port); | 97 | static void genesis_reset(struct skge_hw *hw, int port); |
98 | static void genesis_link_up(struct skge_port *skge); | ||
99 | 99 | ||
100 | static const int txqaddr[] = { Q_XA1, Q_XA2 }; | 100 | static const int txqaddr[] = { Q_XA1, Q_XA2 }; |
101 | static const int rxqaddr[] = { Q_R1, Q_R2 }; | 101 | static const int rxqaddr[] = { Q_R1, Q_R2 }; |
@@ -950,8 +950,7 @@ static void genesis_init(struct skge_hw *hw) | |||
950 | 950 | ||
951 | static void genesis_reset(struct skge_hw *hw, int port) | 951 | static void genesis_reset(struct skge_hw *hw, int port) |
952 | { | 952 | { |
953 | int i; | 953 | const u8 zero[8] = { 0 }; |
954 | u64 zero = 0; | ||
955 | 954 | ||
956 | /* reset the statistics module */ | 955 | /* reset the statistics module */ |
957 | xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT); | 956 | xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT); |
@@ -963,20 +962,100 @@ static void genesis_reset(struct skge_hw *hw, int port) | |||
963 | /* disable Broadcom PHY IRQ */ | 962 | /* disable Broadcom PHY IRQ */ |
964 | xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff); | 963 | xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff); |
965 | 964 | ||
966 | xm_outhash(hw, port, XM_HSM, (u8 *) &zero); | 965 | xm_outhash(hw, port, XM_HSM, zero); |
967 | for (i = 0; i < 15; i++) | ||
968 | xm_outaddr(hw, port, XM_EXM(i), (u8 *) &zero); | ||
969 | xm_outhash(hw, port, XM_SRC_CHK, (u8 *) &zero); | ||
970 | } | 966 | } |
971 | 967 | ||
972 | 968 | ||
973 | static void genesis_mac_init(struct skge_hw *hw, int port) | 969 | /* Convert mode to MII values */ |
970 | static const u16 phy_pause_map[] = { | ||
971 | [FLOW_MODE_NONE] = 0, | ||
972 | [FLOW_MODE_LOC_SEND] = PHY_AN_PAUSE_ASYM, | ||
973 | [FLOW_MODE_SYMMETRIC] = PHY_AN_PAUSE_CAP, | ||
974 | [FLOW_MODE_REM_SEND] = PHY_AN_PAUSE_CAP | PHY_AN_PAUSE_ASYM, | ||
975 | }; | ||
976 | |||
977 | |||
978 | /* Check status of Broadcom phy link */ | ||
979 | static void bcom_check_link(struct skge_hw *hw, int port) | ||
974 | { | 980 | { |
975 | struct skge_port *skge = netdev_priv(hw->dev[port]); | 981 | struct net_device *dev = hw->dev[port]; |
982 | struct skge_port *skge = netdev_priv(dev); | ||
983 | u16 status; | ||
984 | |||
985 | /* read twice because of latch */ | ||
986 | (void) xm_phy_read(hw, port, PHY_BCOM_STAT); | ||
987 | status = xm_phy_read(hw, port, PHY_BCOM_STAT); | ||
988 | |||
989 | pr_debug("bcom_check_link status=0x%x\n", status); | ||
990 | |||
991 | if ((status & PHY_ST_LSYNC) == 0) { | ||
992 | u16 cmd = xm_read16(hw, port, XM_MMU_CMD); | ||
993 | cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); | ||
994 | xm_write16(hw, port, XM_MMU_CMD, cmd); | ||
995 | /* dummy read to ensure writing */ | ||
996 | (void) xm_read16(hw, port, XM_MMU_CMD); | ||
997 | |||
998 | if (netif_carrier_ok(dev)) | ||
999 | skge_link_down(skge); | ||
1000 | } else { | ||
1001 | if (skge->autoneg == AUTONEG_ENABLE && | ||
1002 | (status & PHY_ST_AN_OVER)) { | ||
1003 | u16 lpa = xm_phy_read(hw, port, PHY_BCOM_AUNE_LP); | ||
1004 | u16 aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT); | ||
1005 | |||
1006 | if (lpa & PHY_B_AN_RF) { | ||
1007 | printk(KERN_NOTICE PFX "%s: remote fault\n", | ||
1008 | dev->name); | ||
1009 | return; | ||
1010 | } | ||
1011 | |||
1012 | /* Check Duplex mismatch */ | ||
1013 | switch(aux & PHY_B_AS_AN_RES_MSK) { | ||
1014 | case PHY_B_RES_1000FD: | ||
1015 | skge->duplex = DUPLEX_FULL; | ||
1016 | break; | ||
1017 | case PHY_B_RES_1000HD: | ||
1018 | skge->duplex = DUPLEX_HALF; | ||
1019 | break; | ||
1020 | default: | ||
1021 | printk(KERN_NOTICE PFX "%s: duplex mismatch\n", | ||
1022 | dev->name); | ||
1023 | return; | ||
1024 | } | ||
1025 | |||
1026 | |||
1027 | /* We are using IEEE 802.3z/D5.0 Table 37-4 */ | ||
1028 | switch (aux & PHY_B_AS_PAUSE_MSK) { | ||
1029 | case PHY_B_AS_PAUSE_MSK: | ||
1030 | skge->flow_control = FLOW_MODE_SYMMETRIC; | ||
1031 | break; | ||
1032 | case PHY_B_AS_PRR: | ||
1033 | skge->flow_control = FLOW_MODE_REM_SEND; | ||
1034 | break; | ||
1035 | case PHY_B_AS_PRT: | ||
1036 | skge->flow_control = FLOW_MODE_LOC_SEND; | ||
1037 | break; | ||
1038 | default: | ||
1039 | skge->flow_control = FLOW_MODE_NONE; | ||
1040 | } | ||
1041 | |||
1042 | skge->speed = SPEED_1000; | ||
1043 | } | ||
1044 | |||
1045 | if (!netif_carrier_ok(dev)) | ||
1046 | genesis_link_up(skge); | ||
1047 | } | ||
1048 | } | ||
1049 | |||
1050 | /* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional | ||
1051 | * Phy on for 100 or 10Mbit operation | ||
1052 | */ | ||
1053 | static void bcom_phy_init(struct skge_port *skge, int jumbo) | ||
1054 | { | ||
1055 | struct skge_hw *hw = skge->hw; | ||
1056 | int port = skge->port; | ||
976 | int i; | 1057 | int i; |
977 | u32 r; | 1058 | u16 id1, r, ext, ctl; |
978 | u16 id1; | ||
979 | u16 ctrl1, ctrl2, ctrl3, ctrl4, ctrl5; | ||
980 | 1059 | ||
981 | /* magic workaround patterns for Broadcom */ | 1060 | /* magic workaround patterns for Broadcom */ |
982 | static const struct { | 1061 | static const struct { |
@@ -992,6 +1071,110 @@ static void genesis_mac_init(struct skge_hw *hw, int port) | |||
992 | { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 }, | 1071 | { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 }, |
993 | }; | 1072 | }; |
994 | 1073 | ||
1074 | pr_debug("bcom_phy_init\n"); | ||
1075 | |||
1076 | /* read Id from external PHY (all have the same address) */ | ||
1077 | id1 = xm_phy_read(hw, port, PHY_XMAC_ID1); | ||
1078 | |||
1079 | /* Optimize MDIO transfer by suppressing preamble. */ | ||
1080 | r = xm_read16(hw, port, XM_MMU_CMD); | ||
1081 | r |= XM_MMU_NO_PRE; | ||
1082 | xm_write16(hw, port, XM_MMU_CMD,r); | ||
1083 | |||
1084 | switch(id1) { | ||
1085 | case PHY_BCOM_ID1_C0: | ||
1086 | /* | ||
1087 | * Workaround BCOM Errata for the C0 type. | ||
1088 | * Write magic patterns to reserved registers. | ||
1089 | */ | ||
1090 | for (i = 0; i < ARRAY_SIZE(C0hack); i++) | ||
1091 | xm_phy_write(hw, port, | ||
1092 | C0hack[i].reg, C0hack[i].val); | ||
1093 | |||
1094 | break; | ||
1095 | case PHY_BCOM_ID1_A1: | ||
1096 | /* | ||
1097 | * Workaround BCOM Errata for the A1 type. | ||
1098 | * Write magic patterns to reserved registers. | ||
1099 | */ | ||
1100 | for (i = 0; i < ARRAY_SIZE(A1hack); i++) | ||
1101 | xm_phy_write(hw, port, | ||
1102 | A1hack[i].reg, A1hack[i].val); | ||
1103 | break; | ||
1104 | } | ||
1105 | |||
1106 | /* | ||
1107 | * Workaround BCOM Errata (#10523) for all BCom PHYs. | ||
1108 | * Disable Power Management after reset. | ||
1109 | */ | ||
1110 | r = xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL); | ||
1111 | r |= PHY_B_AC_DIS_PM; | ||
1112 | xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, r); | ||
1113 | |||
1114 | /* Dummy read */ | ||
1115 | xm_read16(hw, port, XM_ISRC); | ||
1116 | |||
1117 | ext = PHY_B_PEC_EN_LTR; /* enable tx led */ | ||
1118 | ctl = PHY_CT_SP1000; /* always 1000mbit */ | ||
1119 | |||
1120 | if (skge->autoneg == AUTONEG_ENABLE) { | ||
1121 | /* | ||
1122 | * Workaround BCOM Errata #1 for the C5 type. | ||
1123 | * 1000Base-T Link Acquisition Failure in Slave Mode | ||
1124 | * Set Repeater/DTE bit 10 of the 1000Base-T Control Register | ||
1125 | */ | ||
1126 | u16 adv = PHY_B_1000C_RD; | ||
1127 | if (skge->advertising & ADVERTISED_1000baseT_Half) | ||
1128 | adv |= PHY_B_1000C_AHD; | ||
1129 | if (skge->advertising & ADVERTISED_1000baseT_Full) | ||
1130 | adv |= PHY_B_1000C_AFD; | ||
1131 | xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, adv); | ||
1132 | |||
1133 | ctl |= PHY_CT_ANE | PHY_CT_RE_CFG; | ||
1134 | } else { | ||
1135 | if (skge->duplex == DUPLEX_FULL) | ||
1136 | ctl |= PHY_CT_DUP_MD; | ||
1137 | /* Force to slave */ | ||
1138 | xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, PHY_B_1000C_MSE); | ||
1139 | } | ||
1140 | |||
1141 | /* Set autonegotiation pause parameters */ | ||
1142 | xm_phy_write(hw, port, PHY_BCOM_AUNE_ADV, | ||
1143 | phy_pause_map[skge->flow_control] | PHY_AN_CSMA); | ||
1144 | |||
1145 | /* Handle Jumbo frames */ | ||
1146 | if (jumbo) { | ||
1147 | xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, | ||
1148 | PHY_B_AC_TX_TST | PHY_B_AC_LONG_PACK); | ||
1149 | |||
1150 | ext |= PHY_B_PEC_HIGH_LA; | ||
1151 | |||
1152 | } | ||
1153 | |||
1154 | xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ext); | ||
1155 | xm_phy_write(hw, port, PHY_BCOM_CTRL, ctl); | ||
1156 | |||
1157 | /* Use link status change interrrupt */ | ||
1158 | xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); | ||
1159 | |||
1160 | bcom_check_link(hw, port); | ||
1161 | } | ||
1162 | |||
1163 | static void genesis_mac_init(struct skge_hw *hw, int port) | ||
1164 | { | ||
1165 | struct net_device *dev = hw->dev[port]; | ||
1166 | struct skge_port *skge = netdev_priv(dev); | ||
1167 | int jumbo = hw->dev[port]->mtu > ETH_DATA_LEN; | ||
1168 | int i; | ||
1169 | u32 r; | ||
1170 | const u8 zero[6] = { 0 }; | ||
1171 | |||
1172 | /* Clear MIB counters */ | ||
1173 | xm_write16(hw, port, XM_STAT_CMD, | ||
1174 | XM_SC_CLR_RXC | XM_SC_CLR_TXC); | ||
1175 | /* Clear two times according to Errata #3 */ | ||
1176 | xm_write16(hw, port, XM_STAT_CMD, | ||
1177 | XM_SC_CLR_RXC | XM_SC_CLR_TXC); | ||
995 | 1178 | ||
996 | /* initialize Rx, Tx and Link LED */ | 1179 | /* initialize Rx, Tx and Link LED */ |
997 | skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); | 1180 | skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); |
@@ -1009,9 +1192,7 @@ static void genesis_mac_init(struct skge_hw *hw, int port) | |||
1009 | * GMII mode. | 1192 | * GMII mode. |
1010 | */ | 1193 | */ |
1011 | spin_lock_bh(&hw->phy_lock); | 1194 | spin_lock_bh(&hw->phy_lock); |
1012 | 1195 | /* Take external Phy out of reset */ | |
1013 | /* External Phy Handling */ | ||
1014 | /* Take PHY out of reset. */ | ||
1015 | r = skge_read32(hw, B2_GP_IO); | 1196 | r = skge_read32(hw, B2_GP_IO); |
1016 | if (port == 0) | 1197 | if (port == 0) |
1017 | r |= GP_DIR_0|GP_IO_0; | 1198 | r |= GP_DIR_0|GP_IO_0; |
@@ -1020,57 +1201,47 @@ static void genesis_mac_init(struct skge_hw *hw, int port) | |||
1020 | 1201 | ||
1021 | skge_write32(hw, B2_GP_IO, r); | 1202 | skge_write32(hw, B2_GP_IO, r); |
1022 | skge_read32(hw, B2_GP_IO); | 1203 | skge_read32(hw, B2_GP_IO); |
1204 | spin_unlock_bh(&hw->phy_lock); | ||
1023 | 1205 | ||
1024 | /* Enable GMII mode on the XMAC. */ | 1206 | /* Enable GMII interfac */ |
1025 | xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); | 1207 | xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); |
1026 | 1208 | ||
1027 | id1 = xm_phy_read(hw, port, PHY_XMAC_ID1); | 1209 | bcom_phy_init(skge, jumbo); |
1028 | 1210 | ||
1029 | /* Optimize MDIO transfer by suppressing preamble. */ | 1211 | /* Set Station Address */ |
1030 | xm_write16(hw, port, XM_MMU_CMD, | 1212 | xm_outaddr(hw, port, XM_SA, dev->dev_addr); |
1031 | xm_read16(hw, port, XM_MMU_CMD) | ||
1032 | | XM_MMU_NO_PRE); | ||
1033 | 1213 | ||
1034 | if (id1 == PHY_BCOM_ID1_C0) { | 1214 | /* We don't use match addresses so clear */ |
1035 | /* | 1215 | for (i = 1; i < 16; i++) |
1036 | * Workaround BCOM Errata for the C0 type. | 1216 | xm_outaddr(hw, port, XM_EXM(i), zero); |
1037 | * Write magic patterns to reserved registers. | 1217 | |
1038 | */ | 1218 | /* configure Rx High Water Mark (XM_RX_HI_WM) */ |
1039 | for (i = 0; i < ARRAY_SIZE(C0hack); i++) | 1219 | xm_write16(hw, port, XM_RX_HI_WM, 1450); |
1040 | xm_phy_write(hw, port, | 1220 | |
1041 | C0hack[i].reg, C0hack[i].val); | 1221 | /* We don't need the FCS appended to the packet. */ |
1222 | r = XM_RX_LENERR_OK | XM_RX_STRIP_FCS; | ||
1223 | if (jumbo) | ||
1224 | r |= XM_RX_BIG_PK_OK; | ||
1042 | 1225 | ||
1043 | } else if (id1 == PHY_BCOM_ID1_A1) { | 1226 | if (skge->duplex == DUPLEX_HALF) { |
1044 | /* | 1227 | /* |
1045 | * Workaround BCOM Errata for the A1 type. | 1228 | * If in manual half duplex mode the other side might be in |
1046 | * Write magic patterns to reserved registers. | 1229 | * full duplex mode, so ignore if a carrier extension is not seen |
1230 | * on frames received | ||
1047 | */ | 1231 | */ |
1048 | for (i = 0; i < ARRAY_SIZE(A1hack); i++) | 1232 | r |= XM_RX_DIS_CEXT; |
1049 | xm_phy_write(hw, port, | ||
1050 | A1hack[i].reg, A1hack[i].val); | ||
1051 | } | 1233 | } |
1234 | xm_write16(hw, port, XM_RX_CMD, r); | ||
1052 | 1235 | ||
1053 | /* | ||
1054 | * Workaround BCOM Errata (#10523) for all BCom PHYs. | ||
1055 | * Disable Power Management after reset. | ||
1056 | */ | ||
1057 | r = xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL); | ||
1058 | xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, r | PHY_B_AC_DIS_PM); | ||
1059 | |||
1060 | |||
1061 | /* Dummy read */ | ||
1062 | xm_read16(hw, port, XM_ISRC); | ||
1063 | |||
1064 | r = xm_read32(hw, port, XM_MODE); | ||
1065 | xm_write32(hw, port, XM_MODE, r|XM_MD_CSA); | ||
1066 | |||
1067 | /* We don't need the FCS appended to the packet. */ | ||
1068 | r = xm_read16(hw, port, XM_RX_CMD); | ||
1069 | xm_write16(hw, port, XM_RX_CMD, r | XM_RX_STRIP_FCS); | ||
1070 | 1236 | ||
1071 | /* We want short frames padded to 60 bytes. */ | 1237 | /* We want short frames padded to 60 bytes. */ |
1072 | r = xm_read16(hw, port, XM_TX_CMD); | 1238 | xm_write16(hw, port, XM_TX_CMD, XM_TX_AUTO_PAD); |
1073 | xm_write16(hw, port, XM_TX_CMD, r | XM_TX_AUTO_PAD); | 1239 | |
1240 | /* | ||
1241 | * Bump up the transmit threshold. This helps hold off transmit | ||
1242 | * underruns when we're blasting traffic from both ports at once. | ||
1243 | */ | ||
1244 | xm_write16(hw, port, XM_TX_THR, 512); | ||
1074 | 1245 | ||
1075 | /* | 1246 | /* |
1076 | * Enable the reception of all error frames. This is is | 1247 | * Enable the reception of all error frames. This is is |
@@ -1086,19 +1257,22 @@ static void genesis_mac_init(struct skge_hw *hw, int port) | |||
1086 | * case the XMAC will start transfering frames out of the | 1257 | * case the XMAC will start transfering frames out of the |
1087 | * RX FIFO as soon as the FIFO threshold is reached. | 1258 | * RX FIFO as soon as the FIFO threshold is reached. |
1088 | */ | 1259 | */ |
1089 | r = xm_read32(hw, port, XM_MODE); | 1260 | xm_write32(hw, port, XM_MODE, XM_DEF_MODE); |
1090 | xm_write32(hw, port, XM_MODE, | ||
1091 | XM_MD_RX_CRCE|XM_MD_RX_LONG|XM_MD_RX_RUNT| | ||
1092 | XM_MD_RX_ERR|XM_MD_RX_IRLE); | ||
1093 | 1261 | ||
1094 | xm_outaddr(hw, port, XM_SA, hw->dev[port]->dev_addr); | ||
1095 | xm_outaddr(hw, port, XM_EXM(0), hw->dev[port]->dev_addr); | ||
1096 | 1262 | ||
1097 | /* | 1263 | /* |
1098 | * Bump up the transmit threshold. This helps hold off transmit | 1264 | * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK) |
1099 | * underruns when we're blasting traffic from both ports at once. | 1265 | * - Enable all bits excepting 'Octets Rx OK Low CntOv' |
1266 | * and 'Octets Rx OK Hi Cnt Ov'. | ||
1100 | */ | 1267 | */ |
1101 | xm_write16(hw, port, XM_TX_THR, 512); | 1268 | xm_write32(hw, port, XM_RX_EV_MSK, XMR_DEF_MSK); |
1269 | |||
1270 | /* | ||
1271 | * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK) | ||
1272 | * - Enable all bits excepting 'Octets Tx OK Low CntOv' | ||
1273 | * and 'Octets Tx OK Hi Cnt Ov'. | ||
1274 | */ | ||
1275 | xm_write32(hw, port, XM_TX_EV_MSK, XMT_DEF_MSK); | ||
1102 | 1276 | ||
1103 | /* Configure MAC arbiter */ | 1277 | /* Configure MAC arbiter */ |
1104 | skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR); | 1278 | skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR); |
@@ -1124,89 +1298,14 @@ static void genesis_mac_init(struct skge_hw *hw, int port) | |||
1124 | skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF); | 1298 | skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF); |
1125 | skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_ENA_OP_MD); | 1299 | skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_ENA_OP_MD); |
1126 | 1300 | ||
1127 | if (hw->dev[port]->mtu > ETH_DATA_LEN) { | 1301 | if (jumbo) { |
1128 | /* Enable frame flushing if jumbo frames used */ | 1302 | /* Enable frame flushing if jumbo frames used */ |
1129 | skge_write16(hw, SK_REG(port,RX_MFF_CTRL1), MFF_ENA_FLUSH); | 1303 | skge_write16(hw, SK_REG(port,RX_MFF_CTRL1), MFF_ENA_FLUSH); |
1130 | } else { | 1304 | } else { |
1131 | /* enable timeout timers if normal frames */ | 1305 | /* enable timeout timers if normal frames */ |
1132 | skge_write16(hw, B3_PA_CTRL, | 1306 | skge_write16(hw, B3_PA_CTRL, |
1133 | port == 0 ? PA_ENA_TO_TX1 : PA_ENA_TO_TX2); | 1307 | (port == 0) ? PA_ENA_TO_TX1 : PA_ENA_TO_TX2); |
1134 | } | 1308 | } |
1135 | |||
1136 | |||
1137 | r = xm_read16(hw, port, XM_RX_CMD); | ||
1138 | if (hw->dev[port]->mtu > ETH_DATA_LEN) | ||
1139 | xm_write16(hw, port, XM_RX_CMD, r | XM_RX_BIG_PK_OK); | ||
1140 | else | ||
1141 | xm_write16(hw, port, XM_RX_CMD, r & ~(XM_RX_BIG_PK_OK)); | ||
1142 | |||
1143 | /* Broadcom phy initialization */ | ||
1144 | ctrl1 = PHY_CT_SP1000; | ||
1145 | ctrl2 = 0; | ||
1146 | ctrl3 = PHY_AN_CSMA; | ||
1147 | ctrl4 = PHY_B_PEC_EN_LTR; | ||
1148 | ctrl5 = PHY_B_AC_TX_TST; | ||
1149 | |||
1150 | if (skge->autoneg == AUTONEG_ENABLE) { | ||
1151 | /* | ||
1152 | * Workaround BCOM Errata #1 for the C5 type. | ||
1153 | * 1000Base-T Link Acquisition Failure in Slave Mode | ||
1154 | * Set Repeater/DTE bit 10 of the 1000Base-T Control Register | ||
1155 | */ | ||
1156 | ctrl2 |= PHY_B_1000C_RD; | ||
1157 | if (skge->advertising & ADVERTISED_1000baseT_Half) | ||
1158 | ctrl2 |= PHY_B_1000C_AHD; | ||
1159 | if (skge->advertising & ADVERTISED_1000baseT_Full) | ||
1160 | ctrl2 |= PHY_B_1000C_AFD; | ||
1161 | |||
1162 | /* Set Flow-control capabilities */ | ||
1163 | switch (skge->flow_control) { | ||
1164 | case FLOW_MODE_NONE: | ||
1165 | ctrl3 |= PHY_B_P_NO_PAUSE; | ||
1166 | break; | ||
1167 | case FLOW_MODE_LOC_SEND: | ||
1168 | ctrl3 |= PHY_B_P_ASYM_MD; | ||
1169 | break; | ||
1170 | case FLOW_MODE_SYMMETRIC: | ||
1171 | ctrl3 |= PHY_B_P_SYM_MD; | ||
1172 | break; | ||
1173 | case FLOW_MODE_REM_SEND: | ||
1174 | ctrl3 |= PHY_B_P_BOTH_MD; | ||
1175 | break; | ||
1176 | } | ||
1177 | |||
1178 | /* Restart Auto-negotiation */ | ||
1179 | ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG; | ||
1180 | } else { | ||
1181 | if (skge->duplex == DUPLEX_FULL) | ||
1182 | ctrl1 |= PHY_CT_DUP_MD; | ||
1183 | |||
1184 | ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */ | ||
1185 | } | ||
1186 | |||
1187 | xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, ctrl2); | ||
1188 | xm_phy_write(hw, port, PHY_BCOM_AUNE_ADV, ctrl3); | ||
1189 | |||
1190 | if (skge->netdev->mtu > ETH_DATA_LEN) { | ||
1191 | ctrl4 |= PHY_B_PEC_HIGH_LA; | ||
1192 | ctrl5 |= PHY_B_AC_LONG_PACK; | ||
1193 | |||
1194 | xm_phy_write(hw, port,PHY_BCOM_AUX_CTRL, ctrl5); | ||
1195 | } | ||
1196 | |||
1197 | xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ctrl4); | ||
1198 | xm_phy_write(hw, port, PHY_BCOM_CTRL, ctrl1); | ||
1199 | spin_unlock_bh(&hw->phy_lock); | ||
1200 | |||
1201 | /* Clear MIB counters */ | ||
1202 | xm_write16(hw, port, XM_STAT_CMD, | ||
1203 | XM_SC_CLR_RXC | XM_SC_CLR_TXC); | ||
1204 | /* Clear two times according to Errata #3 */ | ||
1205 | xm_write16(hw, port, XM_STAT_CMD, | ||
1206 | XM_SC_CLR_RXC | XM_SC_CLR_TXC); | ||
1207 | |||
1208 | /* Start polling for link status */ | ||
1209 | mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ); | ||
1210 | } | 1309 | } |
1211 | 1310 | ||
1212 | static void genesis_stop(struct skge_port *skge) | 1311 | static void genesis_stop(struct skge_port *skge) |
@@ -1331,23 +1430,6 @@ static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg) | |||
1331 | return gma_read16(hw, port, GM_SMI_DATA); | 1430 | return gma_read16(hw, port, GM_SMI_DATA); |
1332 | } | 1431 | } |
1333 | 1432 | ||
1334 | static void genesis_link_down(struct skge_port *skge) | ||
1335 | { | ||
1336 | struct skge_hw *hw = skge->hw; | ||
1337 | int port = skge->port; | ||
1338 | |||
1339 | pr_debug("genesis_link_down\n"); | ||
1340 | |||
1341 | xm_write16(hw, port, XM_MMU_CMD, | ||
1342 | xm_read16(hw, port, XM_MMU_CMD) | ||
1343 | & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX)); | ||
1344 | |||
1345 | /* dummy read to ensure writing */ | ||
1346 | (void) xm_read16(hw, port, XM_MMU_CMD); | ||
1347 | |||
1348 | skge_link_down(skge); | ||
1349 | } | ||
1350 | |||
1351 | static void genesis_link_up(struct skge_port *skge) | 1433 | static void genesis_link_up(struct skge_port *skge) |
1352 | { | 1434 | { |
1353 | struct skge_hw *hw = skge->hw; | 1435 | struct skge_hw *hw = skge->hw; |
@@ -1430,18 +1512,23 @@ static void genesis_link_up(struct skge_port *skge) | |||
1430 | } | 1512 | } |
1431 | 1513 | ||
1432 | 1514 | ||
1433 | static void genesis_bcom_intr(struct skge_port *skge) | 1515 | static inline void bcom_phy_intr(struct skge_port *skge) |
1434 | { | 1516 | { |
1435 | struct skge_hw *hw = skge->hw; | 1517 | struct skge_hw *hw = skge->hw; |
1436 | int port = skge->port; | 1518 | int port = skge->port; |
1437 | u16 stat = xm_phy_read(hw, port, PHY_BCOM_INT_STAT); | 1519 | u16 isrc; |
1520 | |||
1521 | isrc = xm_phy_read(hw, port, PHY_BCOM_INT_STAT); | ||
1522 | pr_debug("bcom_phy_interrupt status=0x%x\n", isrc); | ||
1438 | 1523 | ||
1439 | pr_debug("genesis_bcom intr stat=%x\n", stat); | 1524 | if (isrc & PHY_B_IS_PSE) |
1525 | printk(KERN_ERR PFX "%s: uncorrectable pair swap error\n", | ||
1526 | hw->dev[port]->name); | ||
1440 | 1527 | ||
1441 | /* Workaround BCom Errata: | 1528 | /* Workaround BCom Errata: |
1442 | * enable and disable loopback mode if "NO HCD" occurs. | 1529 | * enable and disable loopback mode if "NO HCD" occurs. |
1443 | */ | 1530 | */ |
1444 | if (stat & PHY_B_IS_NO_HDCL) { | 1531 | if (isrc & PHY_B_IS_NO_HDCL) { |
1445 | u16 ctrl = xm_phy_read(hw, port, PHY_BCOM_CTRL); | 1532 | u16 ctrl = xm_phy_read(hw, port, PHY_BCOM_CTRL); |
1446 | xm_phy_write(hw, port, PHY_BCOM_CTRL, | 1533 | xm_phy_write(hw, port, PHY_BCOM_CTRL, |
1447 | ctrl | PHY_CT_LOOP); | 1534 | ctrl | PHY_CT_LOOP); |
@@ -1449,57 +1536,9 @@ static void genesis_bcom_intr(struct skge_port *skge) | |||
1449 | ctrl & ~PHY_CT_LOOP); | 1536 | ctrl & ~PHY_CT_LOOP); |
1450 | } | 1537 | } |
1451 | 1538 | ||
1452 | stat = xm_phy_read(hw, port, PHY_BCOM_STAT); | 1539 | if (isrc & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) |
1453 | if (stat & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) { | 1540 | bcom_check_link(hw, port); |
1454 | u16 aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT); | ||
1455 | if ( !(aux & PHY_B_AS_LS) && netif_carrier_ok(skge->netdev)) | ||
1456 | genesis_link_down(skge); | ||
1457 | |||
1458 | else if (stat & PHY_B_IS_LST_CHANGE) { | ||
1459 | if (aux & PHY_B_AS_AN_C) { | ||
1460 | switch (aux & PHY_B_AS_AN_RES_MSK) { | ||
1461 | case PHY_B_RES_1000FD: | ||
1462 | skge->duplex = DUPLEX_FULL; | ||
1463 | break; | ||
1464 | case PHY_B_RES_1000HD: | ||
1465 | skge->duplex = DUPLEX_HALF; | ||
1466 | break; | ||
1467 | } | ||
1468 | |||
1469 | switch (aux & PHY_B_AS_PAUSE_MSK) { | ||
1470 | case PHY_B_AS_PAUSE_MSK: | ||
1471 | skge->flow_control = FLOW_MODE_SYMMETRIC; | ||
1472 | break; | ||
1473 | case PHY_B_AS_PRR: | ||
1474 | skge->flow_control = FLOW_MODE_REM_SEND; | ||
1475 | break; | ||
1476 | case PHY_B_AS_PRT: | ||
1477 | skge->flow_control = FLOW_MODE_LOC_SEND; | ||
1478 | break; | ||
1479 | default: | ||
1480 | skge->flow_control = FLOW_MODE_NONE; | ||
1481 | } | ||
1482 | skge->speed = SPEED_1000; | ||
1483 | } | ||
1484 | genesis_link_up(skge); | ||
1485 | } | ||
1486 | else | ||
1487 | mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ); | ||
1488 | } | ||
1489 | } | ||
1490 | |||
1491 | /* Perodic poll of phy status to check for link transistion */ | ||
1492 | static void skge_link_timer(unsigned long __arg) | ||
1493 | { | ||
1494 | struct skge_port *skge = (struct skge_port *) __arg; | ||
1495 | struct skge_hw *hw = skge->hw; | ||
1496 | |||
1497 | if (hw->chip_id != CHIP_ID_GENESIS || !netif_running(skge->netdev)) | ||
1498 | return; | ||
1499 | 1541 | ||
1500 | spin_lock_bh(&hw->phy_lock); | ||
1501 | genesis_bcom_intr(skge); | ||
1502 | spin_unlock_bh(&hw->phy_lock); | ||
1503 | } | 1542 | } |
1504 | 1543 | ||
1505 | /* Marvell Phy Initailization */ | 1544 | /* Marvell Phy Initailization */ |
@@ -1547,41 +1586,12 @@ static void yukon_init(struct skge_hw *hw, int port) | |||
1547 | adv |= PHY_M_AN_10_FD; | 1586 | adv |= PHY_M_AN_10_FD; |
1548 | if (skge->advertising & ADVERTISED_10baseT_Half) | 1587 | if (skge->advertising & ADVERTISED_10baseT_Half) |
1549 | adv |= PHY_M_AN_10_HD; | 1588 | adv |= PHY_M_AN_10_HD; |
1550 | 1589 | } else /* special defines for FIBER (88E1011S only) */ | |
1551 | /* Set Flow-control capabilities */ | ||
1552 | switch (skge->flow_control) { | ||
1553 | case FLOW_MODE_NONE: | ||
1554 | adv |= PHY_B_P_NO_PAUSE; | ||
1555 | break; | ||
1556 | case FLOW_MODE_LOC_SEND: | ||
1557 | adv |= PHY_B_P_ASYM_MD; | ||
1558 | break; | ||
1559 | case FLOW_MODE_SYMMETRIC: | ||
1560 | adv |= PHY_B_P_SYM_MD; | ||
1561 | break; | ||
1562 | case FLOW_MODE_REM_SEND: | ||
1563 | adv |= PHY_B_P_BOTH_MD; | ||
1564 | break; | ||
1565 | } | ||
1566 | } else { /* special defines for FIBER (88E1011S only) */ | ||
1567 | adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; | 1590 | adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; |
1568 | 1591 | ||
1569 | /* Set Flow-control capabilities */ | 1592 | /* Set Flow-control capabilities */ |
1570 | switch (skge->flow_control) { | 1593 | adv |= phy_pause_map[skge->flow_control]; |
1571 | case FLOW_MODE_NONE: | 1594 | |
1572 | adv |= PHY_M_P_NO_PAUSE_X; | ||
1573 | break; | ||
1574 | case FLOW_MODE_LOC_SEND: | ||
1575 | adv |= PHY_M_P_ASYM_MD_X; | ||
1576 | break; | ||
1577 | case FLOW_MODE_SYMMETRIC: | ||
1578 | adv |= PHY_M_P_SYM_MD_X; | ||
1579 | break; | ||
1580 | case FLOW_MODE_REM_SEND: | ||
1581 | adv |= PHY_M_P_BOTH_MD_X; | ||
1582 | break; | ||
1583 | } | ||
1584 | } | ||
1585 | /* Restart Auto-negotiation */ | 1595 | /* Restart Auto-negotiation */ |
1586 | ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG; | 1596 | ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG; |
1587 | } else { | 1597 | } else { |
@@ -2090,7 +2100,6 @@ static int skge_down(struct net_device *dev) | |||
2090 | netif_stop_queue(dev); | 2100 | netif_stop_queue(dev); |
2091 | 2101 | ||
2092 | del_timer_sync(&skge->led_blink); | 2102 | del_timer_sync(&skge->led_blink); |
2093 | del_timer_sync(&skge->link_check); | ||
2094 | 2103 | ||
2095 | /* Stop transmitter */ | 2104 | /* Stop transmitter */ |
2096 | skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); | 2105 | skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); |
@@ -2325,6 +2334,8 @@ static void genesis_set_multicast(struct net_device *dev) | |||
2325 | u32 mode; | 2334 | u32 mode; |
2326 | u8 filter[8]; | 2335 | u8 filter[8]; |
2327 | 2336 | ||
2337 | pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count); | ||
2338 | |||
2328 | mode = xm_read32(hw, port, XM_MODE); | 2339 | mode = xm_read32(hw, port, XM_MODE); |
2329 | mode |= XM_MD_ENA_HASH; | 2340 | mode |= XM_MD_ENA_HASH; |
2330 | if (dev->flags & IFF_PROMISC) | 2341 | if (dev->flags & IFF_PROMISC) |
@@ -2337,16 +2348,15 @@ static void genesis_set_multicast(struct net_device *dev) | |||
2337 | else { | 2348 | else { |
2338 | memset(filter, 0, sizeof(filter)); | 2349 | memset(filter, 0, sizeof(filter)); |
2339 | for (i = 0; list && i < count; i++, list = list->next) { | 2350 | for (i = 0; list && i < count; i++, list = list->next) { |
2340 | u32 crc = crc32_le(~0, list->dmi_addr, ETH_ALEN); | 2351 | u32 crc, bit; |
2341 | u8 bit = 63 - (crc & 63); | 2352 | crc = ether_crc_le(ETH_ALEN, list->dmi_addr); |
2342 | 2353 | bit = ~crc & 0x3f; | |
2343 | filter[bit/8] |= 1 << (bit%8); | 2354 | filter[bit/8] |= 1 << (bit%8); |
2344 | } | 2355 | } |
2345 | } | 2356 | } |
2346 | 2357 | ||
2347 | xm_outhash(hw, port, XM_HSM, filter); | ||
2348 | |||
2349 | xm_write32(hw, port, XM_MODE, mode); | 2358 | xm_write32(hw, port, XM_MODE, mode); |
2359 | xm_outhash(hw, port, XM_HSM, filter); | ||
2350 | } | 2360 | } |
2351 | 2361 | ||
2352 | static void yukon_set_multicast(struct net_device *dev) | 2362 | static void yukon_set_multicast(struct net_device *dev) |
@@ -2667,7 +2677,7 @@ static void skge_extirq(unsigned long data) | |||
2667 | if (hw->chip_id != CHIP_ID_GENESIS) | 2677 | if (hw->chip_id != CHIP_ID_GENESIS) |
2668 | yukon_phy_intr(skge); | 2678 | yukon_phy_intr(skge); |
2669 | else | 2679 | else |
2670 | genesis_bcom_intr(skge); | 2680 | bcom_phy_intr(skge); |
2671 | } | 2681 | } |
2672 | } | 2682 | } |
2673 | spin_unlock(&hw->phy_lock); | 2683 | spin_unlock(&hw->phy_lock); |
@@ -2986,10 +2996,6 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, | |||
2986 | 2996 | ||
2987 | spin_lock_init(&skge->tx_lock); | 2997 | spin_lock_init(&skge->tx_lock); |
2988 | 2998 | ||
2989 | init_timer(&skge->link_check); | ||
2990 | skge->link_check.function = skge_link_timer; | ||
2991 | skge->link_check.data = (unsigned long) skge; | ||
2992 | |||
2993 | init_timer(&skge->led_blink); | 2999 | init_timer(&skge->led_blink); |
2994 | skge->led_blink.function = skge_blink_timer; | 3000 | skge->led_blink.function = skge_blink_timer; |
2995 | skge->led_blink.data = (unsigned long) skge; | 3001 | skge->led_blink.data = (unsigned long) skge; |
diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 6f3a4b56a671..6b9a2ebbab28 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h | |||
@@ -1225,6 +1225,16 @@ enum { | |||
1225 | PHY_B_PES_MLT3_ER = 1<<0, /* Bit 0: MLT3 code Error */ | 1225 | PHY_B_PES_MLT3_ER = 1<<0, /* Bit 0: MLT3 code Error */ |
1226 | }; | 1226 | }; |
1227 | 1227 | ||
1228 | /* PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ | ||
1229 | /* PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ | ||
1230 | enum { | ||
1231 | PHY_B_AN_RF = 1<<13, /* Bit 13: Remote Fault */ | ||
1232 | |||
1233 | PHY_B_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */ | ||
1234 | PHY_B_AN_PC = 1<<10, /* Bit 10: Pause Capable */ | ||
1235 | }; | ||
1236 | |||
1237 | |||
1228 | /***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/ | 1238 | /***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/ |
1229 | enum { | 1239 | enum { |
1230 | PHY_B_FC_CTR = 0xff, /* Bit 7..0: False Carrier Counter */ | 1240 | PHY_B_FC_CTR = 0xff, /* Bit 7..0: False Carrier Counter */ |
@@ -1285,7 +1295,9 @@ enum { | |||
1285 | PHY_B_IS_LST_CHANGE = 1<<1, /* Bit 1: Link Status Changed */ | 1295 | PHY_B_IS_LST_CHANGE = 1<<1, /* Bit 1: Link Status Changed */ |
1286 | PHY_B_IS_CRC_ER = 1<<0, /* Bit 0: CRC Error */ | 1296 | PHY_B_IS_CRC_ER = 1<<0, /* Bit 0: CRC Error */ |
1287 | }; | 1297 | }; |
1288 | #define PHY_B_DEF_MSK (~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) | 1298 | #define PHY_B_DEF_MSK \ |
1299 | (~(PHY_B_IS_PSE | PHY_B_IS_AN_PR | PHY_B_IS_DUP_CHANGE | \ | ||
1300 | PHY_B_IS_LSP_CHANGE | PHY_B_IS_LST_CHANGE)) | ||
1289 | 1301 | ||
1290 | /* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */ | 1302 | /* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */ |
1291 | enum { | 1303 | enum { |
@@ -2489,7 +2501,6 @@ struct skge_port { | |||
2489 | dma_addr_t dma; | 2501 | dma_addr_t dma; |
2490 | unsigned long mem_size; | 2502 | unsigned long mem_size; |
2491 | 2503 | ||
2492 | struct timer_list link_check; | ||
2493 | struct timer_list led_blink; | 2504 | struct timer_list led_blink; |
2494 | }; | 2505 | }; |
2495 | 2506 | ||