diff options
author | Divy Le Ray <divy@chelsio.com> | 2009-05-29 08:52:44 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-29 18:55:04 -0400 |
commit | 744514249f0656e2d50bb57585241670c2d4f32b (patch) | |
tree | f95275ec6dca4be204bdf43df8fce94aba1dc920 /drivers/net/cxgb3/ael1002.c | |
parent | c3a8c5b644118b5e2cfd0690b1dcea904a792c52 (diff) |
cxgb3: Add Aeluros 2020 phy support
Add support for the AEL2020 phy.
Add PCI IDs of the boards using this phy.
Signed-off-by: Divy Le Ray <divy@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/cxgb3/ael1002.c')
-rw-r--r-- | drivers/net/cxgb3/ael1002.c | 823 |
1 files changed, 758 insertions, 65 deletions
diff --git a/drivers/net/cxgb3/ael1002.c b/drivers/net/cxgb3/ael1002.c index df1f58576689..9fe008ec9ba5 100644 --- a/drivers/net/cxgb3/ael1002.c +++ b/drivers/net/cxgb3/ael1002.c | |||
@@ -44,12 +44,33 @@ enum { | |||
44 | AEL_I2C_STAT = 0xc30c, | 44 | AEL_I2C_STAT = 0xc30c, |
45 | AEL2005_GPIO_CTRL = 0xc214, | 45 | AEL2005_GPIO_CTRL = 0xc214, |
46 | AEL2005_GPIO_STAT = 0xc215, | 46 | AEL2005_GPIO_STAT = 0xc215, |
47 | |||
48 | AEL2020_GPIO_INTR = 0xc103, /* Latch High (LH) */ | ||
49 | AEL2020_GPIO_CTRL = 0xc108, /* Store Clear (SC) */ | ||
50 | AEL2020_GPIO_STAT = 0xc10c, /* Read Only (RO) */ | ||
51 | AEL2020_GPIO_CFG = 0xc110, /* Read Write (RW) */ | ||
52 | |||
53 | AEL2020_GPIO_SDA = 0, /* IN: i2c serial data */ | ||
54 | AEL2020_GPIO_MODDET = 1, /* IN: Module Detect */ | ||
55 | AEL2020_GPIO_0 = 3, /* IN: unassigned */ | ||
56 | AEL2020_GPIO_1 = 2, /* OUT: unassigned */ | ||
57 | AEL2020_GPIO_LSTAT = AEL2020_GPIO_1, /* wired to link status LED */ | ||
47 | }; | 58 | }; |
48 | 59 | ||
49 | enum { edc_none, edc_sr, edc_twinax }; | 60 | enum { edc_none, edc_sr, edc_twinax }; |
50 | 61 | ||
51 | /* PHY module I2C device address */ | 62 | /* PHY module I2C device address */ |
52 | #define MODULE_DEV_ADDR 0xa0 | 63 | enum { |
64 | MODULE_DEV_ADDR = 0xa0, | ||
65 | SFF_DEV_ADDR = 0xa2, | ||
66 | }; | ||
67 | |||
68 | /* PHY transceiver type */ | ||
69 | enum { | ||
70 | phy_transtype_unknown = 0, | ||
71 | phy_transtype_sfp = 3, | ||
72 | phy_transtype_xfp = 6, | ||
73 | }; | ||
53 | 74 | ||
54 | #define AEL2005_MODDET_IRQ 4 | 75 | #define AEL2005_MODDET_IRQ 4 |
55 | 76 | ||
@@ -86,6 +107,37 @@ static void ael100x_txon(struct cphy *phy) | |||
86 | msleep(30); | 107 | msleep(30); |
87 | } | 108 | } |
88 | 109 | ||
110 | /* | ||
111 | * Read an 8-bit word from a device attached to the PHY's i2c bus. | ||
112 | */ | ||
113 | static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr) | ||
114 | { | ||
115 | int i, err; | ||
116 | unsigned int stat, data; | ||
117 | |||
118 | err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL_I2C_CTRL, | ||
119 | (dev_addr << 8) | (1 << 8) | word_addr); | ||
120 | if (err) | ||
121 | return err; | ||
122 | |||
123 | for (i = 0; i < 200; i++) { | ||
124 | msleep(1); | ||
125 | err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_STAT, &stat); | ||
126 | if (err) | ||
127 | return err; | ||
128 | if ((stat & 3) == 1) { | ||
129 | err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_DATA, | ||
130 | &data); | ||
131 | if (err) | ||
132 | return err; | ||
133 | return data >> 8; | ||
134 | } | ||
135 | } | ||
136 | CH_WARN(phy->adapter, "PHY %u i2c read of dev.addr %#x.%#x timed out\n", | ||
137 | phy->mdio.prtad, dev_addr, word_addr); | ||
138 | return -ETIMEDOUT; | ||
139 | } | ||
140 | |||
89 | static int ael1002_power_down(struct cphy *phy, int enable) | 141 | static int ael1002_power_down(struct cphy *phy, int enable) |
90 | { | 142 | { |
91 | int err; | 143 | int err; |
@@ -199,6 +251,51 @@ int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter, | |||
199 | return 0; | 251 | return 0; |
200 | } | 252 | } |
201 | 253 | ||
254 | /* | ||
255 | * Decode our module type. | ||
256 | */ | ||
257 | static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms) | ||
258 | { | ||
259 | int v; | ||
260 | |||
261 | if (delay_ms) | ||
262 | msleep(delay_ms); | ||
263 | |||
264 | /* see SFF-8472 for below */ | ||
265 | v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3); | ||
266 | if (v < 0) | ||
267 | return v; | ||
268 | |||
269 | if (v == 0x10) | ||
270 | return phy_modtype_sr; | ||
271 | if (v == 0x20) | ||
272 | return phy_modtype_lr; | ||
273 | if (v == 0x40) | ||
274 | return phy_modtype_lrm; | ||
275 | |||
276 | v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6); | ||
277 | if (v < 0) | ||
278 | return v; | ||
279 | if (v != 4) | ||
280 | goto unknown; | ||
281 | |||
282 | v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10); | ||
283 | if (v < 0) | ||
284 | return v; | ||
285 | |||
286 | if (v & 0x80) { | ||
287 | v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12); | ||
288 | if (v < 0) | ||
289 | return v; | ||
290 | return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax; | ||
291 | } | ||
292 | unknown: | ||
293 | return phy_modtype_unknown; | ||
294 | } | ||
295 | |||
296 | /* | ||
297 | * Code to support the Aeluros/NetLogic 2005 10Gb PHY. | ||
298 | */ | ||
202 | static int ael2005_setup_sr_edc(struct cphy *phy) | 299 | static int ael2005_setup_sr_edc(struct cphy *phy) |
203 | { | 300 | { |
204 | static struct reg_val regs[] = { | 301 | static struct reg_val regs[] = { |
@@ -893,35 +990,7 @@ static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype) | |||
893 | return err; | 990 | return err; |
894 | } | 991 | } |
895 | 992 | ||
896 | static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr) | 993 | static int ael2005_get_module_type(struct cphy *phy, int delay_ms) |
897 | { | ||
898 | int i, err; | ||
899 | unsigned int stat, data; | ||
900 | |||
901 | err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL_I2C_CTRL, | ||
902 | (dev_addr << 8) | (1 << 8) | word_addr); | ||
903 | if (err) | ||
904 | return err; | ||
905 | |||
906 | for (i = 0; i < 5; i++) { | ||
907 | msleep(1); | ||
908 | err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_STAT, &stat); | ||
909 | if (err) | ||
910 | return err; | ||
911 | if ((stat & 3) == 1) { | ||
912 | err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL_I2C_DATA, | ||
913 | &data); | ||
914 | if (err) | ||
915 | return err; | ||
916 | return data >> 8; | ||
917 | } | ||
918 | } | ||
919 | CH_WARN(phy->adapter, "PHY %u I2C read of addr %u timed out\n", | ||
920 | phy->mdio.prtad, word_addr); | ||
921 | return -ETIMEDOUT; | ||
922 | } | ||
923 | |||
924 | static int get_module_type(struct cphy *phy, int delay_ms) | ||
925 | { | 994 | { |
926 | int v; | 995 | int v; |
927 | unsigned int stat; | 996 | unsigned int stat; |
@@ -933,39 +1002,7 @@ static int get_module_type(struct cphy *phy, int delay_ms) | |||
933 | if (stat & (1 << 8)) /* module absent */ | 1002 | if (stat & (1 << 8)) /* module absent */ |
934 | return phy_modtype_none; | 1003 | return phy_modtype_none; |
935 | 1004 | ||
936 | if (delay_ms) | 1005 | return ael2xxx_get_module_type(phy, delay_ms); |
937 | msleep(delay_ms); | ||
938 | |||
939 | /* see SFF-8472 for below */ | ||
940 | v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 3); | ||
941 | if (v < 0) | ||
942 | return v; | ||
943 | |||
944 | if (v == 0x10) | ||
945 | return phy_modtype_sr; | ||
946 | if (v == 0x20) | ||
947 | return phy_modtype_lr; | ||
948 | if (v == 0x40) | ||
949 | return phy_modtype_lrm; | ||
950 | |||
951 | v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 6); | ||
952 | if (v < 0) | ||
953 | return v; | ||
954 | if (v != 4) | ||
955 | goto unknown; | ||
956 | |||
957 | v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 10); | ||
958 | if (v < 0) | ||
959 | return v; | ||
960 | |||
961 | if (v & 0x80) { | ||
962 | v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0x12); | ||
963 | if (v < 0) | ||
964 | return v; | ||
965 | return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax; | ||
966 | } | ||
967 | unknown: | ||
968 | return phy_modtype_unknown; | ||
969 | } | 1006 | } |
970 | 1007 | ||
971 | static int ael2005_intr_enable(struct cphy *phy) | 1008 | static int ael2005_intr_enable(struct cphy *phy) |
@@ -1024,7 +1061,7 @@ static int ael2005_reset(struct cphy *phy, int wait) | |||
1024 | 1061 | ||
1025 | msleep(50); | 1062 | msleep(50); |
1026 | 1063 | ||
1027 | err = get_module_type(phy, 0); | 1064 | err = ael2005_get_module_type(phy, 0); |
1028 | if (err < 0) | 1065 | if (err < 0) |
1029 | return err; | 1066 | return err; |
1030 | phy->modtype = err; | 1067 | phy->modtype = err; |
@@ -1062,7 +1099,7 @@ static int ael2005_intr_handler(struct cphy *phy) | |||
1062 | return ret; | 1099 | return ret; |
1063 | 1100 | ||
1064 | /* modules have max 300 ms init time after hot plug */ | 1101 | /* modules have max 300 ms init time after hot plug */ |
1065 | ret = get_module_type(phy, 300); | 1102 | ret = ael2005_get_module_type(phy, 300); |
1066 | if (ret < 0) | 1103 | if (ret < 0) |
1067 | return ret; | 1104 | return ret; |
1068 | 1105 | ||
@@ -1113,6 +1150,662 @@ int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter, | |||
1113 | } | 1150 | } |
1114 | 1151 | ||
1115 | /* | 1152 | /* |
1153 | * Setup EDC and other parameters for operation with an optical module. | ||
1154 | */ | ||
1155 | static int ael2020_setup_sr_edc(struct cphy *phy) | ||
1156 | { | ||
1157 | static struct reg_val regs[] = { | ||
1158 | /* set CDR offset to 10 */ | ||
1159 | { MDIO_MMD_PMAPMD, 0xcc01, 0xffff, 0x488a }, | ||
1160 | |||
1161 | /* adjust 10G RX bias current */ | ||
1162 | { MDIO_MMD_PMAPMD, 0xcb1b, 0xffff, 0x0200 }, | ||
1163 | { MDIO_MMD_PMAPMD, 0xcb1c, 0xffff, 0x00f0 }, | ||
1164 | { MDIO_MMD_PMAPMD, 0xcc06, 0xffff, 0x00e0 }, | ||
1165 | |||
1166 | /* end */ | ||
1167 | { 0, 0, 0, 0 } | ||
1168 | }; | ||
1169 | int err; | ||
1170 | |||
1171 | err = set_phy_regs(phy, regs); | ||
1172 | msleep(50); | ||
1173 | if (err) | ||
1174 | return err; | ||
1175 | |||
1176 | phy->priv = edc_sr; | ||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | /* | ||
1181 | * Setup EDC and other parameters for operation with an TWINAX module. | ||
1182 | */ | ||
1183 | static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype) | ||
1184 | { | ||
1185 | /* set uC to 40MHz */ | ||
1186 | static struct reg_val uCclock40MHz[] = { | ||
1187 | { MDIO_MMD_PMAPMD, 0xff28, 0xffff, 0x4001 }, | ||
1188 | { MDIO_MMD_PMAPMD, 0xff2a, 0xffff, 0x0002 }, | ||
1189 | { 0, 0, 0, 0 } | ||
1190 | }; | ||
1191 | |||
1192 | /* activate uC clock */ | ||
1193 | static struct reg_val uCclockActivate[] = { | ||
1194 | { MDIO_MMD_PMAPMD, 0xd000, 0xffff, 0x5200 }, | ||
1195 | { 0, 0, 0, 0 } | ||
1196 | }; | ||
1197 | |||
1198 | /* set PC to start of SRAM and activate uC */ | ||
1199 | static struct reg_val uCactivate[] = { | ||
1200 | { MDIO_MMD_PMAPMD, 0xd080, 0xffff, 0x0100 }, | ||
1201 | { MDIO_MMD_PMAPMD, 0xd092, 0xffff, 0x0000 }, | ||
1202 | { 0, 0, 0, 0 } | ||
1203 | }; | ||
1204 | |||
1205 | /* TWINAX EDC firmware */ | ||
1206 | static u16 twinax_edc[] = { | ||
1207 | 0xd800, 0x4009, | ||
1208 | 0xd801, 0x2fff, | ||
1209 | 0xd802, 0x300f, | ||
1210 | 0xd803, 0x40aa, | ||
1211 | 0xd804, 0x401c, | ||
1212 | 0xd805, 0x401e, | ||
1213 | 0xd806, 0x2ff4, | ||
1214 | 0xd807, 0x3dc4, | ||
1215 | 0xd808, 0x2035, | ||
1216 | 0xd809, 0x3035, | ||
1217 | 0xd80a, 0x6524, | ||
1218 | 0xd80b, 0x2cb2, | ||
1219 | 0xd80c, 0x3012, | ||
1220 | 0xd80d, 0x1002, | ||
1221 | 0xd80e, 0x26e2, | ||
1222 | 0xd80f, 0x3022, | ||
1223 | 0xd810, 0x1002, | ||
1224 | 0xd811, 0x27d2, | ||
1225 | 0xd812, 0x3022, | ||
1226 | 0xd813, 0x1002, | ||
1227 | 0xd814, 0x2822, | ||
1228 | 0xd815, 0x3012, | ||
1229 | 0xd816, 0x1002, | ||
1230 | 0xd817, 0x2492, | ||
1231 | 0xd818, 0x3022, | ||
1232 | 0xd819, 0x1002, | ||
1233 | 0xd81a, 0x2772, | ||
1234 | 0xd81b, 0x3012, | ||
1235 | 0xd81c, 0x1002, | ||
1236 | 0xd81d, 0x23d2, | ||
1237 | 0xd81e, 0x3022, | ||
1238 | 0xd81f, 0x1002, | ||
1239 | 0xd820, 0x22cd, | ||
1240 | 0xd821, 0x301d, | ||
1241 | 0xd822, 0x27f2, | ||
1242 | 0xd823, 0x3022, | ||
1243 | 0xd824, 0x1002, | ||
1244 | 0xd825, 0x5553, | ||
1245 | 0xd826, 0x0307, | ||
1246 | 0xd827, 0x2522, | ||
1247 | 0xd828, 0x3022, | ||
1248 | 0xd829, 0x1002, | ||
1249 | 0xd82a, 0x2142, | ||
1250 | 0xd82b, 0x3012, | ||
1251 | 0xd82c, 0x1002, | ||
1252 | 0xd82d, 0x4016, | ||
1253 | 0xd82e, 0x5e63, | ||
1254 | 0xd82f, 0x0344, | ||
1255 | 0xd830, 0x2142, | ||
1256 | 0xd831, 0x3012, | ||
1257 | 0xd832, 0x1002, | ||
1258 | 0xd833, 0x400e, | ||
1259 | 0xd834, 0x2522, | ||
1260 | 0xd835, 0x3022, | ||
1261 | 0xd836, 0x1002, | ||
1262 | 0xd837, 0x2b52, | ||
1263 | 0xd838, 0x3012, | ||
1264 | 0xd839, 0x1002, | ||
1265 | 0xd83a, 0x2742, | ||
1266 | 0xd83b, 0x3022, | ||
1267 | 0xd83c, 0x1002, | ||
1268 | 0xd83d, 0x25e2, | ||
1269 | 0xd83e, 0x3022, | ||
1270 | 0xd83f, 0x1002, | ||
1271 | 0xd840, 0x2fa4, | ||
1272 | 0xd841, 0x3dc4, | ||
1273 | 0xd842, 0x6624, | ||
1274 | 0xd843, 0x414b, | ||
1275 | 0xd844, 0x56b3, | ||
1276 | 0xd845, 0x03c6, | ||
1277 | 0xd846, 0x866b, | ||
1278 | 0xd847, 0x400c, | ||
1279 | 0xd848, 0x2712, | ||
1280 | 0xd849, 0x3012, | ||
1281 | 0xd84a, 0x1002, | ||
1282 | 0xd84b, 0x2c4b, | ||
1283 | 0xd84c, 0x309b, | ||
1284 | 0xd84d, 0x56b3, | ||
1285 | 0xd84e, 0x03c3, | ||
1286 | 0xd84f, 0x866b, | ||
1287 | 0xd850, 0x400c, | ||
1288 | 0xd851, 0x2272, | ||
1289 | 0xd852, 0x3022, | ||
1290 | 0xd853, 0x1002, | ||
1291 | 0xd854, 0x2742, | ||
1292 | 0xd855, 0x3022, | ||
1293 | 0xd856, 0x1002, | ||
1294 | 0xd857, 0x25e2, | ||
1295 | 0xd858, 0x3022, | ||
1296 | 0xd859, 0x1002, | ||
1297 | 0xd85a, 0x2fb4, | ||
1298 | 0xd85b, 0x3dc4, | ||
1299 | 0xd85c, 0x6624, | ||
1300 | 0xd85d, 0x56b3, | ||
1301 | 0xd85e, 0x03c3, | ||
1302 | 0xd85f, 0x866b, | ||
1303 | 0xd860, 0x401c, | ||
1304 | 0xd861, 0x2c45, | ||
1305 | 0xd862, 0x3095, | ||
1306 | 0xd863, 0x5b53, | ||
1307 | 0xd864, 0x2372, | ||
1308 | 0xd865, 0x3012, | ||
1309 | 0xd866, 0x13c2, | ||
1310 | 0xd867, 0x5cc3, | ||
1311 | 0xd868, 0x2712, | ||
1312 | 0xd869, 0x3012, | ||
1313 | 0xd86a, 0x1312, | ||
1314 | 0xd86b, 0x2b52, | ||
1315 | 0xd86c, 0x3012, | ||
1316 | 0xd86d, 0x1002, | ||
1317 | 0xd86e, 0x2742, | ||
1318 | 0xd86f, 0x3022, | ||
1319 | 0xd870, 0x1002, | ||
1320 | 0xd871, 0x2582, | ||
1321 | 0xd872, 0x3022, | ||
1322 | 0xd873, 0x1002, | ||
1323 | 0xd874, 0x2142, | ||
1324 | 0xd875, 0x3012, | ||
1325 | 0xd876, 0x1002, | ||
1326 | 0xd877, 0x628f, | ||
1327 | 0xd878, 0x2985, | ||
1328 | 0xd879, 0x33a5, | ||
1329 | 0xd87a, 0x25e2, | ||
1330 | 0xd87b, 0x3022, | ||
1331 | 0xd87c, 0x1002, | ||
1332 | 0xd87d, 0x5653, | ||
1333 | 0xd87e, 0x03d2, | ||
1334 | 0xd87f, 0x401e, | ||
1335 | 0xd880, 0x6f72, | ||
1336 | 0xd881, 0x1002, | ||
1337 | 0xd882, 0x628f, | ||
1338 | 0xd883, 0x2304, | ||
1339 | 0xd884, 0x3c84, | ||
1340 | 0xd885, 0x6436, | ||
1341 | 0xd886, 0xdff4, | ||
1342 | 0xd887, 0x6436, | ||
1343 | 0xd888, 0x2ff5, | ||
1344 | 0xd889, 0x3005, | ||
1345 | 0xd88a, 0x8656, | ||
1346 | 0xd88b, 0xdfba, | ||
1347 | 0xd88c, 0x56a3, | ||
1348 | 0xd88d, 0xd05a, | ||
1349 | 0xd88e, 0x2972, | ||
1350 | 0xd88f, 0x3012, | ||
1351 | 0xd890, 0x1392, | ||
1352 | 0xd891, 0xd05a, | ||
1353 | 0xd892, 0x56a3, | ||
1354 | 0xd893, 0xdfba, | ||
1355 | 0xd894, 0x0383, | ||
1356 | 0xd895, 0x6f72, | ||
1357 | 0xd896, 0x1002, | ||
1358 | 0xd897, 0x2b45, | ||
1359 | 0xd898, 0x3005, | ||
1360 | 0xd899, 0x4178, | ||
1361 | 0xd89a, 0x5653, | ||
1362 | 0xd89b, 0x0384, | ||
1363 | 0xd89c, 0x2a62, | ||
1364 | 0xd89d, 0x3012, | ||
1365 | 0xd89e, 0x1002, | ||
1366 | 0xd89f, 0x2f05, | ||
1367 | 0xd8a0, 0x3005, | ||
1368 | 0xd8a1, 0x41c8, | ||
1369 | 0xd8a2, 0x5653, | ||
1370 | 0xd8a3, 0x0382, | ||
1371 | 0xd8a4, 0x0002, | ||
1372 | 0xd8a5, 0x4218, | ||
1373 | 0xd8a6, 0x2474, | ||
1374 | 0xd8a7, 0x3c84, | ||
1375 | 0xd8a8, 0x6437, | ||
1376 | 0xd8a9, 0xdff4, | ||
1377 | 0xd8aa, 0x6437, | ||
1378 | 0xd8ab, 0x2ff5, | ||
1379 | 0xd8ac, 0x3c05, | ||
1380 | 0xd8ad, 0x8757, | ||
1381 | 0xd8ae, 0xb888, | ||
1382 | 0xd8af, 0x9787, | ||
1383 | 0xd8b0, 0xdff4, | ||
1384 | 0xd8b1, 0x6724, | ||
1385 | 0xd8b2, 0x866a, | ||
1386 | 0xd8b3, 0x6f72, | ||
1387 | 0xd8b4, 0x1002, | ||
1388 | 0xd8b5, 0x2641, | ||
1389 | 0xd8b6, 0x3021, | ||
1390 | 0xd8b7, 0x1001, | ||
1391 | 0xd8b8, 0xc620, | ||
1392 | 0xd8b9, 0x0000, | ||
1393 | 0xd8ba, 0xc621, | ||
1394 | 0xd8bb, 0x0000, | ||
1395 | 0xd8bc, 0xc622, | ||
1396 | 0xd8bd, 0x00ce, | ||
1397 | 0xd8be, 0xc623, | ||
1398 | 0xd8bf, 0x007f, | ||
1399 | 0xd8c0, 0xc624, | ||
1400 | 0xd8c1, 0x0032, | ||
1401 | 0xd8c2, 0xc625, | ||
1402 | 0xd8c3, 0x0000, | ||
1403 | 0xd8c4, 0xc627, | ||
1404 | 0xd8c5, 0x0000, | ||
1405 | 0xd8c6, 0xc628, | ||
1406 | 0xd8c7, 0x0000, | ||
1407 | 0xd8c8, 0xc62c, | ||
1408 | 0xd8c9, 0x0000, | ||
1409 | 0xd8ca, 0x0000, | ||
1410 | 0xd8cb, 0x2641, | ||
1411 | 0xd8cc, 0x3021, | ||
1412 | 0xd8cd, 0x1001, | ||
1413 | 0xd8ce, 0xc502, | ||
1414 | 0xd8cf, 0x53ac, | ||
1415 | 0xd8d0, 0xc503, | ||
1416 | 0xd8d1, 0x2cd3, | ||
1417 | 0xd8d2, 0xc600, | ||
1418 | 0xd8d3, 0x2a6e, | ||
1419 | 0xd8d4, 0xc601, | ||
1420 | 0xd8d5, 0x2a2c, | ||
1421 | 0xd8d6, 0xc605, | ||
1422 | 0xd8d7, 0x5557, | ||
1423 | 0xd8d8, 0xc60c, | ||
1424 | 0xd8d9, 0x5400, | ||
1425 | 0xd8da, 0xc710, | ||
1426 | 0xd8db, 0x0700, | ||
1427 | 0xd8dc, 0xc711, | ||
1428 | 0xd8dd, 0x0f06, | ||
1429 | 0xd8de, 0xc718, | ||
1430 | 0xd8df, 0x0700, | ||
1431 | 0xd8e0, 0xc719, | ||
1432 | 0xd8e1, 0x0f06, | ||
1433 | 0xd8e2, 0xc720, | ||
1434 | 0xd8e3, 0x4700, | ||
1435 | 0xd8e4, 0xc721, | ||
1436 | 0xd8e5, 0x0f06, | ||
1437 | 0xd8e6, 0xc728, | ||
1438 | 0xd8e7, 0x0700, | ||
1439 | 0xd8e8, 0xc729, | ||
1440 | 0xd8e9, 0x1207, | ||
1441 | 0xd8ea, 0xc801, | ||
1442 | 0xd8eb, 0x7f50, | ||
1443 | 0xd8ec, 0xc802, | ||
1444 | 0xd8ed, 0x7760, | ||
1445 | 0xd8ee, 0xc803, | ||
1446 | 0xd8ef, 0x7fce, | ||
1447 | 0xd8f0, 0xc804, | ||
1448 | 0xd8f1, 0x520e, | ||
1449 | 0xd8f2, 0xc805, | ||
1450 | 0xd8f3, 0x5c11, | ||
1451 | 0xd8f4, 0xc806, | ||
1452 | 0xd8f5, 0x3c51, | ||
1453 | 0xd8f6, 0xc807, | ||
1454 | 0xd8f7, 0x4061, | ||
1455 | 0xd8f8, 0xc808, | ||
1456 | 0xd8f9, 0x49c1, | ||
1457 | 0xd8fa, 0xc809, | ||
1458 | 0xd8fb, 0x3840, | ||
1459 | 0xd8fc, 0xc80a, | ||
1460 | 0xd8fd, 0x0000, | ||
1461 | 0xd8fe, 0xc821, | ||
1462 | 0xd8ff, 0x0002, | ||
1463 | 0xd900, 0xc822, | ||
1464 | 0xd901, 0x0046, | ||
1465 | 0xd902, 0xc844, | ||
1466 | 0xd903, 0x182f, | ||
1467 | 0xd904, 0xc013, | ||
1468 | 0xd905, 0xf341, | ||
1469 | 0xd906, 0xc084, | ||
1470 | 0xd907, 0x0030, | ||
1471 | 0xd908, 0xc904, | ||
1472 | 0xd909, 0x1401, | ||
1473 | 0xd90a, 0xcb0c, | ||
1474 | 0xd90b, 0x0004, | ||
1475 | 0xd90c, 0xcb0e, | ||
1476 | 0xd90d, 0xa00a, | ||
1477 | 0xd90e, 0xcb0f, | ||
1478 | 0xd90f, 0xc0c0, | ||
1479 | 0xd910, 0xcb10, | ||
1480 | 0xd911, 0xc0c0, | ||
1481 | 0xd912, 0xcb11, | ||
1482 | 0xd913, 0x00a0, | ||
1483 | 0xd914, 0xcb12, | ||
1484 | 0xd915, 0x0007, | ||
1485 | 0xd916, 0xc241, | ||
1486 | 0xd917, 0xa000, | ||
1487 | 0xd918, 0xc243, | ||
1488 | 0xd919, 0x7fe0, | ||
1489 | 0xd91a, 0xc604, | ||
1490 | 0xd91b, 0x000e, | ||
1491 | 0xd91c, 0xc609, | ||
1492 | 0xd91d, 0x00f5, | ||
1493 | 0xd91e, 0xc611, | ||
1494 | 0xd91f, 0x000e, | ||
1495 | 0xd920, 0xc660, | ||
1496 | 0xd921, 0x9600, | ||
1497 | 0xd922, 0xc687, | ||
1498 | 0xd923, 0x0004, | ||
1499 | 0xd924, 0xc60a, | ||
1500 | 0xd925, 0x04f5, | ||
1501 | 0xd926, 0x0000, | ||
1502 | 0xd927, 0x2641, | ||
1503 | 0xd928, 0x3021, | ||
1504 | 0xd929, 0x1001, | ||
1505 | 0xd92a, 0xc620, | ||
1506 | 0xd92b, 0x14e5, | ||
1507 | 0xd92c, 0xc621, | ||
1508 | 0xd92d, 0xc53d, | ||
1509 | 0xd92e, 0xc622, | ||
1510 | 0xd92f, 0x3cbe, | ||
1511 | 0xd930, 0xc623, | ||
1512 | 0xd931, 0x4452, | ||
1513 | 0xd932, 0xc624, | ||
1514 | 0xd933, 0xc5c5, | ||
1515 | 0xd934, 0xc625, | ||
1516 | 0xd935, 0xe01e, | ||
1517 | 0xd936, 0xc627, | ||
1518 | 0xd937, 0x0000, | ||
1519 | 0xd938, 0xc628, | ||
1520 | 0xd939, 0x0000, | ||
1521 | 0xd93a, 0xc62c, | ||
1522 | 0xd93b, 0x0000, | ||
1523 | 0xd93c, 0x0000, | ||
1524 | 0xd93d, 0x2b84, | ||
1525 | 0xd93e, 0x3c74, | ||
1526 | 0xd93f, 0x6435, | ||
1527 | 0xd940, 0xdff4, | ||
1528 | 0xd941, 0x6435, | ||
1529 | 0xd942, 0x2806, | ||
1530 | 0xd943, 0x3006, | ||
1531 | 0xd944, 0x8565, | ||
1532 | 0xd945, 0x2b24, | ||
1533 | 0xd946, 0x3c24, | ||
1534 | 0xd947, 0x6436, | ||
1535 | 0xd948, 0x1002, | ||
1536 | 0xd949, 0x2b24, | ||
1537 | 0xd94a, 0x3c24, | ||
1538 | 0xd94b, 0x6436, | ||
1539 | 0xd94c, 0x4045, | ||
1540 | 0xd94d, 0x8656, | ||
1541 | 0xd94e, 0x5663, | ||
1542 | 0xd94f, 0x0302, | ||
1543 | 0xd950, 0x401e, | ||
1544 | 0xd951, 0x1002, | ||
1545 | 0xd952, 0x2807, | ||
1546 | 0xd953, 0x31a7, | ||
1547 | 0xd954, 0x20c4, | ||
1548 | 0xd955, 0x3c24, | ||
1549 | 0xd956, 0x6724, | ||
1550 | 0xd957, 0x1002, | ||
1551 | 0xd958, 0x2807, | ||
1552 | 0xd959, 0x3187, | ||
1553 | 0xd95a, 0x20c4, | ||
1554 | 0xd95b, 0x3c24, | ||
1555 | 0xd95c, 0x6724, | ||
1556 | 0xd95d, 0x1002, | ||
1557 | 0xd95e, 0x24f4, | ||
1558 | 0xd95f, 0x3c64, | ||
1559 | 0xd960, 0x6436, | ||
1560 | 0xd961, 0xdff4, | ||
1561 | 0xd962, 0x6436, | ||
1562 | 0xd963, 0x1002, | ||
1563 | 0xd964, 0x2006, | ||
1564 | 0xd965, 0x3d76, | ||
1565 | 0xd966, 0xc161, | ||
1566 | 0xd967, 0x6134, | ||
1567 | 0xd968, 0x6135, | ||
1568 | 0xd969, 0x5443, | ||
1569 | 0xd96a, 0x0303, | ||
1570 | 0xd96b, 0x6524, | ||
1571 | 0xd96c, 0x00fb, | ||
1572 | 0xd96d, 0x1002, | ||
1573 | 0xd96e, 0x20d4, | ||
1574 | 0xd96f, 0x3c24, | ||
1575 | 0xd970, 0x2025, | ||
1576 | 0xd971, 0x3005, | ||
1577 | 0xd972, 0x6524, | ||
1578 | 0xd973, 0x1002, | ||
1579 | 0xd974, 0xd019, | ||
1580 | 0xd975, 0x2104, | ||
1581 | 0xd976, 0x3c24, | ||
1582 | 0xd977, 0x2105, | ||
1583 | 0xd978, 0x3805, | ||
1584 | 0xd979, 0x6524, | ||
1585 | 0xd97a, 0xdff4, | ||
1586 | 0xd97b, 0x4005, | ||
1587 | 0xd97c, 0x6524, | ||
1588 | 0xd97d, 0x2e8d, | ||
1589 | 0xd97e, 0x303d, | ||
1590 | 0xd97f, 0x2408, | ||
1591 | 0xd980, 0x35d8, | ||
1592 | 0xd981, 0x5dd3, | ||
1593 | 0xd982, 0x0307, | ||
1594 | 0xd983, 0x8887, | ||
1595 | 0xd984, 0x63a7, | ||
1596 | 0xd985, 0x8887, | ||
1597 | 0xd986, 0x63a7, | ||
1598 | 0xd987, 0xdffd, | ||
1599 | 0xd988, 0x00f9, | ||
1600 | 0xd989, 0x1002, | ||
1601 | 0xd98a, 0x0000, | ||
1602 | }; | ||
1603 | int i, err; | ||
1604 | |||
1605 | /* set uC clock and activate it */ | ||
1606 | err = set_phy_regs(phy, uCclock40MHz); | ||
1607 | msleep(500); | ||
1608 | if (err) | ||
1609 | return err; | ||
1610 | err = set_phy_regs(phy, uCclockActivate); | ||
1611 | msleep(500); | ||
1612 | if (err) | ||
1613 | return err; | ||
1614 | |||
1615 | /* write TWINAX EDC firmware into PHY */ | ||
1616 | for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2) | ||
1617 | err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, twinax_edc[i], | ||
1618 | twinax_edc[i + 1]); | ||
1619 | /* activate uC */ | ||
1620 | err = set_phy_regs(phy, uCactivate); | ||
1621 | if (!err) | ||
1622 | phy->priv = edc_twinax; | ||
1623 | return err; | ||
1624 | } | ||
1625 | |||
1626 | /* | ||
1627 | * Return Module Type. | ||
1628 | */ | ||
1629 | static int ael2020_get_module_type(struct cphy *phy, int delay_ms) | ||
1630 | { | ||
1631 | int v; | ||
1632 | unsigned int stat; | ||
1633 | |||
1634 | v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_STAT, &stat); | ||
1635 | if (v) | ||
1636 | return v; | ||
1637 | |||
1638 | if (stat & (0x1 << (AEL2020_GPIO_MODDET*4))) { | ||
1639 | /* module absent */ | ||
1640 | return phy_modtype_none; | ||
1641 | } | ||
1642 | |||
1643 | return ael2xxx_get_module_type(phy, delay_ms); | ||
1644 | } | ||
1645 | |||
1646 | /* | ||
1647 | * Enable PHY interrupts. We enable "Module Detection" interrupts (on any | ||
1648 | * state transition) and then generic Link Alarm Status Interrupt (LASI). | ||
1649 | */ | ||
1650 | static int ael2020_intr_enable(struct cphy *phy) | ||
1651 | { | ||
1652 | int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL, | ||
1653 | 0x2 << (AEL2020_GPIO_MODDET*4)); | ||
1654 | return err ? err : t3_phy_lasi_intr_enable(phy); | ||
1655 | } | ||
1656 | |||
1657 | /* | ||
1658 | * Disable PHY interrupts. The mirror of the above ... | ||
1659 | */ | ||
1660 | static int ael2020_intr_disable(struct cphy *phy) | ||
1661 | { | ||
1662 | int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL, | ||
1663 | 0x1 << (AEL2020_GPIO_MODDET*4)); | ||
1664 | return err ? err : t3_phy_lasi_intr_disable(phy); | ||
1665 | } | ||
1666 | |||
1667 | /* | ||
1668 | * Clear PHY interrupt state. | ||
1669 | */ | ||
1670 | static int ael2020_intr_clear(struct cphy *phy) | ||
1671 | { | ||
1672 | /* | ||
1673 | * The GPIO Interrupt register on the AEL2020 is a "Latching High" | ||
1674 | * (LH) register which is cleared to the current state when it's read. | ||
1675 | * Thus, we simply read the register and discard the result. | ||
1676 | */ | ||
1677 | unsigned int stat; | ||
1678 | int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_INTR, &stat); | ||
1679 | return err ? err : t3_phy_lasi_intr_clear(phy); | ||
1680 | } | ||
1681 | |||
1682 | /* | ||
1683 | * Reset the PHY and put it into a canonical operating state. | ||
1684 | */ | ||
1685 | static int ael2020_reset(struct cphy *phy, int wait) | ||
1686 | { | ||
1687 | static struct reg_val regs0[] = { | ||
1688 | /* Erratum #2: CDRLOL asserted, causing PMA link down status */ | ||
1689 | { MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x3101 }, | ||
1690 | |||
1691 | /* force XAUI to send LF when RX_LOS is asserted */ | ||
1692 | { MDIO_MMD_PMAPMD, 0xcd40, 0xffff, 0x0001 }, | ||
1693 | |||
1694 | /* RX_LOS pin is active high */ | ||
1695 | { MDIO_MMD_PMAPMD, AEL_OPT_SETTINGS, | ||
1696 | 0x0020, 0x0020 }, | ||
1697 | |||
1698 | /* output Module's Loss Of Signal (LOS) to LED */ | ||
1699 | { MDIO_MMD_PMAPMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT, | ||
1700 | 0xffff, 0x0004 }, | ||
1701 | { MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL, | ||
1702 | 0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) }, | ||
1703 | |||
1704 | /* end */ | ||
1705 | { 0, 0, 0, 0 } | ||
1706 | }; | ||
1707 | int err; | ||
1708 | unsigned int lasi_ctrl; | ||
1709 | |||
1710 | /* grab current interrupt state */ | ||
1711 | err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, | ||
1712 | &lasi_ctrl); | ||
1713 | if (err) | ||
1714 | return err; | ||
1715 | |||
1716 | err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 125); | ||
1717 | if (err) | ||
1718 | return err; | ||
1719 | msleep(100); | ||
1720 | |||
1721 | /* basic initialization for all module types */ | ||
1722 | phy->priv = edc_none; | ||
1723 | err = set_phy_regs(phy, regs0); | ||
1724 | if (err) | ||
1725 | return err; | ||
1726 | |||
1727 | /* determine module type and perform appropriate initialization */ | ||
1728 | err = ael2020_get_module_type(phy, 0); | ||
1729 | if (err < 0) | ||
1730 | return err; | ||
1731 | phy->modtype = (u8)err; | ||
1732 | if (err == phy_modtype_twinax || err == phy_modtype_twinax_long) | ||
1733 | err = ael2020_setup_twinax_edc(phy, err); | ||
1734 | else | ||
1735 | err = ael2020_setup_sr_edc(phy); | ||
1736 | if (err) | ||
1737 | return err; | ||
1738 | |||
1739 | /* reset wipes out interrupts, reenable them if they were on */ | ||
1740 | if (lasi_ctrl & 1) | ||
1741 | err = ael2005_intr_enable(phy); | ||
1742 | return err; | ||
1743 | } | ||
1744 | |||
1745 | /* | ||
1746 | * Handle a PHY interrupt. | ||
1747 | */ | ||
1748 | static int ael2020_intr_handler(struct cphy *phy) | ||
1749 | { | ||
1750 | unsigned int stat; | ||
1751 | int ret, edc_needed, cause = 0; | ||
1752 | |||
1753 | ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_INTR, &stat); | ||
1754 | if (ret) | ||
1755 | return ret; | ||
1756 | |||
1757 | if (stat & (0x1 << AEL2020_GPIO_MODDET)) { | ||
1758 | /* modules have max 300 ms init time after hot plug */ | ||
1759 | ret = ael2020_get_module_type(phy, 300); | ||
1760 | if (ret < 0) | ||
1761 | return ret; | ||
1762 | |||
1763 | phy->modtype = (u8)ret; | ||
1764 | if (ret == phy_modtype_none) | ||
1765 | edc_needed = phy->priv; /* on unplug retain EDC */ | ||
1766 | else if (ret == phy_modtype_twinax || | ||
1767 | ret == phy_modtype_twinax_long) | ||
1768 | edc_needed = edc_twinax; | ||
1769 | else | ||
1770 | edc_needed = edc_sr; | ||
1771 | |||
1772 | if (edc_needed != phy->priv) { | ||
1773 | ret = ael2020_reset(phy, 0); | ||
1774 | return ret ? ret : cphy_cause_module_change; | ||
1775 | } | ||
1776 | cause = cphy_cause_module_change; | ||
1777 | } | ||
1778 | |||
1779 | ret = t3_phy_lasi_intr_handler(phy); | ||
1780 | if (ret < 0) | ||
1781 | return ret; | ||
1782 | |||
1783 | ret |= cause; | ||
1784 | return ret ? ret : cphy_cause_link_change; | ||
1785 | } | ||
1786 | |||
1787 | static struct cphy_ops ael2020_ops = { | ||
1788 | .reset = ael2020_reset, | ||
1789 | .intr_enable = ael2020_intr_enable, | ||
1790 | .intr_disable = ael2020_intr_disable, | ||
1791 | .intr_clear = ael2020_intr_clear, | ||
1792 | .intr_handler = ael2020_intr_handler, | ||
1793 | .get_link_status = get_link_status_r, | ||
1794 | .power_down = ael1002_power_down, | ||
1795 | .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, | ||
1796 | }; | ||
1797 | |||
1798 | int t3_ael2020_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, | ||
1799 | const struct mdio_ops *mdio_ops) | ||
1800 | { | ||
1801 | cphy_init(phy, adapter, phy_addr, &ael2020_ops, mdio_ops, | ||
1802 | SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE | | ||
1803 | SUPPORTED_IRQ, "10GBASE-R"); | ||
1804 | msleep(125); | ||
1805 | return 0; | ||
1806 | } | ||
1807 | |||
1808 | /* | ||
1116 | * Get link status for a 10GBASE-X device. | 1809 | * Get link status for a 10GBASE-X device. |
1117 | */ | 1810 | */ |
1118 | static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed, | 1811 | static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed, |