blob: 66e47f76f32b7c88bea8d3830f32033edd6353bf [file] [log] [blame]
Divy Le Ray4d22de32007-01-18 22:04:14 -05001/*
Divy Le Raya02d44a2008-10-13 18:47:30 -07002 * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
Divy Le Ray4d22de32007-01-18 22:04:14 -05003 *
Divy Le Ray1d68e932007-01-30 19:44:35 -08004 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
Divy Le Ray4d22de32007-01-18 22:04:14 -05009 *
Divy Le Ray1d68e932007-01-30 19:44:35 -080010 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
Divy Le Ray4d22de32007-01-18 22:04:14 -050031 */
Divy Le Ray4d22de32007-01-18 22:04:14 -050032#include "common.h"
33#include "regs.h"
34
35enum {
Divy Le Ray4d22de32007-01-18 22:04:14 -050036 AEL100X_TX_CONFIG1 = 0xc002,
37 AEL1002_PWR_DOWN_HI = 0xc011,
38 AEL1002_PWR_DOWN_LO = 0xc012,
39 AEL1002_XFI_EQL = 0xc015,
40 AEL1002_LB_EN = 0xc017,
Divy Le Ray1e882022008-10-08 17:40:07 -070041 AEL_OPT_SETTINGS = 0xc017,
42 AEL_I2C_CTRL = 0xc30a,
43 AEL_I2C_DATA = 0xc30b,
44 AEL_I2C_STAT = 0xc30c,
45 AEL2005_GPIO_CTRL = 0xc214,
46 AEL2005_GPIO_STAT = 0xc215,
Divy Le Ray74451422009-05-29 12:52:44 +000047
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 */
Divy Le Ray4d22de32007-01-18 22:04:14 -050058};
59
Divy Le Ray1e882022008-10-08 17:40:07 -070060enum { edc_none, edc_sr, edc_twinax };
61
62/* PHY module I2C device address */
Divy Le Ray74451422009-05-29 12:52:44 +000063enum {
64 MODULE_DEV_ADDR = 0xa0,
65 SFF_DEV_ADDR = 0xa2,
66};
67
68/* PHY transceiver type */
69enum {
70 phy_transtype_unknown = 0,
71 phy_transtype_sfp = 3,
72 phy_transtype_xfp = 6,
73};
Divy Le Ray1e882022008-10-08 17:40:07 -070074
75#define AEL2005_MODDET_IRQ 4
76
77struct reg_val {
78 unsigned short mmd_addr;
79 unsigned short reg_addr;
80 unsigned short clear_bits;
81 unsigned short set_bits;
82};
83
84static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
85{
86 int err;
87
88 for (err = 0; rv->mmd_addr && !err; rv++) {
89 if (rv->clear_bits == 0xffff)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +000090 err = t3_mdio_write(phy, rv->mmd_addr, rv->reg_addr,
91 rv->set_bits);
Divy Le Ray1e882022008-10-08 17:40:07 -070092 else
93 err = t3_mdio_change_bits(phy, rv->mmd_addr,
94 rv->reg_addr, rv->clear_bits,
95 rv->set_bits);
96 }
97 return err;
98}
99
Divy Le Ray4d22de32007-01-18 22:04:14 -0500100static void ael100x_txon(struct cphy *phy)
101{
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000102 int tx_on_gpio =
103 phy->mdio.prtad == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
Divy Le Ray4d22de32007-01-18 22:04:14 -0500104
105 msleep(100);
106 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
107 msleep(30);
108}
109
Divy Le Ray74451422009-05-29 12:52:44 +0000110/*
111 * Read an 8-bit word from a device attached to the PHY's i2c bus.
112 */
113static 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
Divy Le Ray4d22de32007-01-18 22:04:14 -0500141static int ael1002_power_down(struct cphy *phy, int enable)
142{
143 int err;
144
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000145 err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, !!enable);
Divy Le Ray4d22de32007-01-18 22:04:14 -0500146 if (!err)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000147 err = mdio_set_flag(&phy->mdio, phy->mdio.prtad,
148 MDIO_MMD_PMAPMD, MDIO_CTRL1,
149 MDIO_CTRL1_LPOWER, enable);
Divy Le Ray4d22de32007-01-18 22:04:14 -0500150 return err;
151}
152
153static int ael1002_reset(struct cphy *phy, int wait)
154{
155 int err;
156
157 if ((err = ael1002_power_down(phy, 0)) ||
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000158 (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL100X_TX_CONFIG1, 1)) ||
159 (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_HI, 0)) ||
160 (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_PWR_DOWN_LO, 0)) ||
161 (err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL1002_XFI_EQL, 0x18)) ||
162 (err = t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL1002_LB_EN,
Divy Le Ray4d22de32007-01-18 22:04:14 -0500163 0, 1 << 5)))
164 return err;
165 return 0;
166}
167
168static int ael1002_intr_noop(struct cphy *phy)
169{
170 return 0;
171}
172
Divy Le Ray1e882022008-10-08 17:40:07 -0700173/*
174 * Get link status for a 10GBASE-R device.
175 */
176static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed,
177 int *duplex, int *fc)
Divy Le Ray4d22de32007-01-18 22:04:14 -0500178{
179 if (link_ok) {
Divy Le Ray1e882022008-10-08 17:40:07 -0700180 unsigned int stat0, stat1, stat2;
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000181 int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
182 MDIO_PMA_RXDET, &stat0);
Divy Le Ray4d22de32007-01-18 22:04:14 -0500183
Divy Le Ray1e882022008-10-08 17:40:07 -0700184 if (!err)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000185 err = t3_mdio_read(phy, MDIO_MMD_PCS,
186 MDIO_PCS_10GBRT_STAT1, &stat1);
Divy Le Ray1e882022008-10-08 17:40:07 -0700187 if (!err)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000188 err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
189 MDIO_PHYXS_LNSTAT, &stat2);
Divy Le Ray4d22de32007-01-18 22:04:14 -0500190 if (err)
191 return err;
Divy Le Ray1e882022008-10-08 17:40:07 -0700192 *link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
Divy Le Ray4d22de32007-01-18 22:04:14 -0500193 }
194 if (speed)
195 *speed = SPEED_10000;
196 if (duplex)
197 *duplex = DUPLEX_FULL;
198 return 0;
199}
200
201static struct cphy_ops ael1002_ops = {
202 .reset = ael1002_reset,
203 .intr_enable = ael1002_intr_noop,
204 .intr_disable = ael1002_intr_noop,
205 .intr_clear = ael1002_intr_noop,
206 .intr_handler = ael1002_intr_noop,
Divy Le Ray1e882022008-10-08 17:40:07 -0700207 .get_link_status = get_link_status_r,
Divy Le Ray4d22de32007-01-18 22:04:14 -0500208 .power_down = ael1002_power_down,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000209 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
Divy Le Ray4d22de32007-01-18 22:04:14 -0500210};
211
Divy Le Ray78e46892008-10-08 17:38:01 -0700212int t3_ael1002_phy_prep(struct cphy *phy, struct adapter *adapter,
213 int phy_addr, const struct mdio_ops *mdio_ops)
Divy Le Ray4d22de32007-01-18 22:04:14 -0500214{
Divy Le Ray04497982008-10-08 17:38:29 -0700215 cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops,
216 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
217 "10GBASE-R");
Divy Le Ray4d22de32007-01-18 22:04:14 -0500218 ael100x_txon(phy);
Divy Le Ray78e46892008-10-08 17:38:01 -0700219 return 0;
Divy Le Ray4d22de32007-01-18 22:04:14 -0500220}
221
222static int ael1006_reset(struct cphy *phy, int wait)
223{
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000224 return t3_phy_reset(phy, MDIO_MMD_PMAPMD, wait);
Divy Le Ray4d22de32007-01-18 22:04:14 -0500225}
226
Divy Le Ray4d22de32007-01-18 22:04:14 -0500227static struct cphy_ops ael1006_ops = {
228 .reset = ael1006_reset,
Divy Le Ray9b1e3652008-10-08 17:39:31 -0700229 .intr_enable = t3_phy_lasi_intr_enable,
230 .intr_disable = t3_phy_lasi_intr_disable,
231 .intr_clear = t3_phy_lasi_intr_clear,
232 .intr_handler = t3_phy_lasi_intr_handler,
Divy Le Ray1e882022008-10-08 17:40:07 -0700233 .get_link_status = get_link_status_r,
Divy Le Ray619f05c2009-07-07 19:48:53 +0000234 .power_down = ael1002_power_down,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000235 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
Divy Le Ray4d22de32007-01-18 22:04:14 -0500236};
237
Divy Le Ray78e46892008-10-08 17:38:01 -0700238int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
239 int phy_addr, const struct mdio_ops *mdio_ops)
Divy Le Ray4d22de32007-01-18 22:04:14 -0500240{
Divy Le Ray04497982008-10-08 17:38:29 -0700241 cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops,
242 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
243 "10GBASE-SR");
Divy Le Ray4d22de32007-01-18 22:04:14 -0500244 ael100x_txon(phy);
Divy Le Ray78e46892008-10-08 17:38:01 -0700245 return 0;
Divy Le Ray4d22de32007-01-18 22:04:14 -0500246}
247
Divy Le Ray74451422009-05-29 12:52:44 +0000248/*
249 * Decode our module type.
250 */
251static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms)
252{
253 int v;
254
255 if (delay_ms)
256 msleep(delay_ms);
257
258 /* see SFF-8472 for below */
259 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3);
260 if (v < 0)
261 return v;
262
263 if (v == 0x10)
264 return phy_modtype_sr;
265 if (v == 0x20)
266 return phy_modtype_lr;
267 if (v == 0x40)
268 return phy_modtype_lrm;
269
270 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6);
271 if (v < 0)
272 return v;
273 if (v != 4)
274 goto unknown;
275
276 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10);
277 if (v < 0)
278 return v;
279
280 if (v & 0x80) {
281 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
282 if (v < 0)
283 return v;
284 return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax;
285 }
286unknown:
287 return phy_modtype_unknown;
288}
289
290/*
291 * Code to support the Aeluros/NetLogic 2005 10Gb PHY.
292 */
Divy Le Ray1e882022008-10-08 17:40:07 -0700293static int ael2005_setup_sr_edc(struct cphy *phy)
294{
295 static struct reg_val regs[] = {
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000296 { MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x181 },
297 { MDIO_MMD_PMAPMD, 0xc010, 0xffff, 0x448a },
298 { MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5200 },
Divy Le Ray1e882022008-10-08 17:40:07 -0700299 { 0, 0, 0, 0 }
300 };
301 static u16 sr_edc[] = {
302 0xcc00, 0x2ff4,
303 0xcc01, 0x3cd4,
304 0xcc02, 0x2015,
305 0xcc03, 0x3105,
306 0xcc04, 0x6524,
307 0xcc05, 0x27ff,
308 0xcc06, 0x300f,
309 0xcc07, 0x2c8b,
310 0xcc08, 0x300b,
311 0xcc09, 0x4009,
312 0xcc0a, 0x400e,
313 0xcc0b, 0x2f72,
314 0xcc0c, 0x3002,
315 0xcc0d, 0x1002,
316 0xcc0e, 0x2172,
317 0xcc0f, 0x3012,
318 0xcc10, 0x1002,
319 0xcc11, 0x25d2,
320 0xcc12, 0x3012,
321 0xcc13, 0x1002,
322 0xcc14, 0xd01e,
323 0xcc15, 0x27d2,
324 0xcc16, 0x3012,
325 0xcc17, 0x1002,
326 0xcc18, 0x2004,
327 0xcc19, 0x3c84,
328 0xcc1a, 0x6436,
329 0xcc1b, 0x2007,
330 0xcc1c, 0x3f87,
331 0xcc1d, 0x8676,
332 0xcc1e, 0x40b7,
333 0xcc1f, 0xa746,
334 0xcc20, 0x4047,
335 0xcc21, 0x5673,
336 0xcc22, 0x2982,
337 0xcc23, 0x3002,
338 0xcc24, 0x13d2,
339 0xcc25, 0x8bbd,
340 0xcc26, 0x2862,
341 0xcc27, 0x3012,
342 0xcc28, 0x1002,
343 0xcc29, 0x2092,
344 0xcc2a, 0x3012,
345 0xcc2b, 0x1002,
346 0xcc2c, 0x5cc3,
347 0xcc2d, 0x314,
348 0xcc2e, 0x2942,
349 0xcc2f, 0x3002,
350 0xcc30, 0x1002,
351 0xcc31, 0xd019,
352 0xcc32, 0x2032,
353 0xcc33, 0x3012,
354 0xcc34, 0x1002,
355 0xcc35, 0x2a04,
356 0xcc36, 0x3c74,
357 0xcc37, 0x6435,
358 0xcc38, 0x2fa4,
359 0xcc39, 0x3cd4,
360 0xcc3a, 0x6624,
361 0xcc3b, 0x5563,
362 0xcc3c, 0x2d42,
363 0xcc3d, 0x3002,
364 0xcc3e, 0x13d2,
365 0xcc3f, 0x464d,
366 0xcc40, 0x2862,
367 0xcc41, 0x3012,
368 0xcc42, 0x1002,
369 0xcc43, 0x2032,
370 0xcc44, 0x3012,
371 0xcc45, 0x1002,
372 0xcc46, 0x2fb4,
373 0xcc47, 0x3cd4,
374 0xcc48, 0x6624,
375 0xcc49, 0x5563,
376 0xcc4a, 0x2d42,
377 0xcc4b, 0x3002,
378 0xcc4c, 0x13d2,
379 0xcc4d, 0x2ed2,
380 0xcc4e, 0x3002,
381 0xcc4f, 0x1002,
382 0xcc50, 0x2fd2,
383 0xcc51, 0x3002,
384 0xcc52, 0x1002,
385 0xcc53, 0x004,
386 0xcc54, 0x2942,
387 0xcc55, 0x3002,
388 0xcc56, 0x1002,
389 0xcc57, 0x2092,
390 0xcc58, 0x3012,
391 0xcc59, 0x1002,
392 0xcc5a, 0x5cc3,
393 0xcc5b, 0x317,
394 0xcc5c, 0x2f72,
395 0xcc5d, 0x3002,
396 0xcc5e, 0x1002,
397 0xcc5f, 0x2942,
398 0xcc60, 0x3002,
399 0xcc61, 0x1002,
400 0xcc62, 0x22cd,
401 0xcc63, 0x301d,
402 0xcc64, 0x2862,
403 0xcc65, 0x3012,
404 0xcc66, 0x1002,
405 0xcc67, 0x2ed2,
406 0xcc68, 0x3002,
407 0xcc69, 0x1002,
408 0xcc6a, 0x2d72,
409 0xcc6b, 0x3002,
410 0xcc6c, 0x1002,
411 0xcc6d, 0x628f,
412 0xcc6e, 0x2112,
413 0xcc6f, 0x3012,
414 0xcc70, 0x1002,
415 0xcc71, 0x5aa3,
416 0xcc72, 0x2dc2,
417 0xcc73, 0x3002,
418 0xcc74, 0x1312,
419 0xcc75, 0x6f72,
420 0xcc76, 0x1002,
421 0xcc77, 0x2807,
422 0xcc78, 0x31a7,
423 0xcc79, 0x20c4,
424 0xcc7a, 0x3c24,
425 0xcc7b, 0x6724,
426 0xcc7c, 0x1002,
427 0xcc7d, 0x2807,
428 0xcc7e, 0x3187,
429 0xcc7f, 0x20c4,
430 0xcc80, 0x3c24,
431 0xcc81, 0x6724,
432 0xcc82, 0x1002,
433 0xcc83, 0x2514,
434 0xcc84, 0x3c64,
435 0xcc85, 0x6436,
436 0xcc86, 0xdff4,
437 0xcc87, 0x6436,
438 0xcc88, 0x1002,
439 0xcc89, 0x40a4,
440 0xcc8a, 0x643c,
441 0xcc8b, 0x4016,
442 0xcc8c, 0x8c6c,
443 0xcc8d, 0x2b24,
444 0xcc8e, 0x3c24,
445 0xcc8f, 0x6435,
446 0xcc90, 0x1002,
447 0xcc91, 0x2b24,
448 0xcc92, 0x3c24,
449 0xcc93, 0x643a,
450 0xcc94, 0x4025,
451 0xcc95, 0x8a5a,
452 0xcc96, 0x1002,
453 0xcc97, 0x2731,
454 0xcc98, 0x3011,
455 0xcc99, 0x1001,
456 0xcc9a, 0xc7a0,
457 0xcc9b, 0x100,
458 0xcc9c, 0xc502,
459 0xcc9d, 0x53ac,
460 0xcc9e, 0xc503,
461 0xcc9f, 0xd5d5,
462 0xcca0, 0xc600,
463 0xcca1, 0x2a6d,
464 0xcca2, 0xc601,
465 0xcca3, 0x2a4c,
466 0xcca4, 0xc602,
467 0xcca5, 0x111,
468 0xcca6, 0xc60c,
469 0xcca7, 0x5900,
470 0xcca8, 0xc710,
471 0xcca9, 0x700,
472 0xccaa, 0xc718,
473 0xccab, 0x700,
474 0xccac, 0xc720,
475 0xccad, 0x4700,
476 0xccae, 0xc801,
477 0xccaf, 0x7f50,
478 0xccb0, 0xc802,
479 0xccb1, 0x7760,
480 0xccb2, 0xc803,
481 0xccb3, 0x7fce,
482 0xccb4, 0xc804,
483 0xccb5, 0x5700,
484 0xccb6, 0xc805,
485 0xccb7, 0x5f11,
486 0xccb8, 0xc806,
487 0xccb9, 0x4751,
488 0xccba, 0xc807,
489 0xccbb, 0x57e1,
490 0xccbc, 0xc808,
491 0xccbd, 0x2700,
492 0xccbe, 0xc809,
493 0xccbf, 0x000,
494 0xccc0, 0xc821,
495 0xccc1, 0x002,
496 0xccc2, 0xc822,
497 0xccc3, 0x014,
498 0xccc4, 0xc832,
499 0xccc5, 0x1186,
500 0xccc6, 0xc847,
501 0xccc7, 0x1e02,
502 0xccc8, 0xc013,
503 0xccc9, 0xf341,
504 0xccca, 0xc01a,
505 0xcccb, 0x446,
506 0xcccc, 0xc024,
507 0xcccd, 0x1000,
508 0xccce, 0xc025,
509 0xcccf, 0xa00,
510 0xccd0, 0xc026,
511 0xccd1, 0xc0c,
512 0xccd2, 0xc027,
513 0xccd3, 0xc0c,
514 0xccd4, 0xc029,
515 0xccd5, 0x0a0,
516 0xccd6, 0xc030,
517 0xccd7, 0xa00,
518 0xccd8, 0xc03c,
519 0xccd9, 0x01c,
520 0xccda, 0xc005,
521 0xccdb, 0x7a06,
522 0xccdc, 0x000,
523 0xccdd, 0x2731,
524 0xccde, 0x3011,
525 0xccdf, 0x1001,
526 0xcce0, 0xc620,
527 0xcce1, 0x000,
528 0xcce2, 0xc621,
529 0xcce3, 0x03f,
530 0xcce4, 0xc622,
531 0xcce5, 0x000,
532 0xcce6, 0xc623,
533 0xcce7, 0x000,
534 0xcce8, 0xc624,
535 0xcce9, 0x000,
536 0xccea, 0xc625,
537 0xcceb, 0x000,
538 0xccec, 0xc627,
539 0xcced, 0x000,
540 0xccee, 0xc628,
541 0xccef, 0x000,
542 0xccf0, 0xc62c,
543 0xccf1, 0x000,
544 0xccf2, 0x000,
545 0xccf3, 0x2806,
546 0xccf4, 0x3cb6,
547 0xccf5, 0xc161,
548 0xccf6, 0x6134,
549 0xccf7, 0x6135,
550 0xccf8, 0x5443,
551 0xccf9, 0x303,
552 0xccfa, 0x6524,
553 0xccfb, 0x00b,
554 0xccfc, 0x1002,
555 0xccfd, 0x2104,
556 0xccfe, 0x3c24,
557 0xccff, 0x2105,
558 0xcd00, 0x3805,
559 0xcd01, 0x6524,
560 0xcd02, 0xdff4,
561 0xcd03, 0x4005,
562 0xcd04, 0x6524,
563 0xcd05, 0x1002,
564 0xcd06, 0x5dd3,
565 0xcd07, 0x306,
566 0xcd08, 0x2ff7,
567 0xcd09, 0x38f7,
568 0xcd0a, 0x60b7,
569 0xcd0b, 0xdffd,
570 0xcd0c, 0x00a,
571 0xcd0d, 0x1002,
572 0xcd0e, 0
573 };
574 int i, err;
575
576 err = set_phy_regs(phy, regs);
577 if (err)
578 return err;
579
580 msleep(50);
581
582 for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000583 err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, sr_edc[i],
584 sr_edc[i + 1]);
Divy Le Ray1e882022008-10-08 17:40:07 -0700585 if (!err)
586 phy->priv = edc_sr;
587 return err;
588}
589
590static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
591{
592 static struct reg_val regs[] = {
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000593 { MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5a00 },
Divy Le Ray1e882022008-10-08 17:40:07 -0700594 { 0, 0, 0, 0 }
595 };
596 static struct reg_val preemphasis[] = {
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000597 { MDIO_MMD_PMAPMD, 0xc014, 0xffff, 0xfe16 },
598 { MDIO_MMD_PMAPMD, 0xc015, 0xffff, 0xa000 },
Divy Le Ray1e882022008-10-08 17:40:07 -0700599 { 0, 0, 0, 0 }
600 };
601 static u16 twinax_edc[] = {
602 0xcc00, 0x4009,
603 0xcc01, 0x27ff,
604 0xcc02, 0x300f,
605 0xcc03, 0x40aa,
606 0xcc04, 0x401c,
607 0xcc05, 0x401e,
608 0xcc06, 0x2ff4,
609 0xcc07, 0x3cd4,
610 0xcc08, 0x2035,
611 0xcc09, 0x3145,
612 0xcc0a, 0x6524,
613 0xcc0b, 0x26a2,
614 0xcc0c, 0x3012,
615 0xcc0d, 0x1002,
616 0xcc0e, 0x29c2,
617 0xcc0f, 0x3002,
618 0xcc10, 0x1002,
619 0xcc11, 0x2072,
620 0xcc12, 0x3012,
621 0xcc13, 0x1002,
622 0xcc14, 0x22cd,
623 0xcc15, 0x301d,
624 0xcc16, 0x2e52,
625 0xcc17, 0x3012,
626 0xcc18, 0x1002,
627 0xcc19, 0x28e2,
628 0xcc1a, 0x3002,
629 0xcc1b, 0x1002,
630 0xcc1c, 0x628f,
631 0xcc1d, 0x2ac2,
632 0xcc1e, 0x3012,
633 0xcc1f, 0x1002,
634 0xcc20, 0x5553,
635 0xcc21, 0x2ae2,
636 0xcc22, 0x3002,
637 0xcc23, 0x1302,
638 0xcc24, 0x401e,
639 0xcc25, 0x2be2,
640 0xcc26, 0x3012,
641 0xcc27, 0x1002,
642 0xcc28, 0x2da2,
643 0xcc29, 0x3012,
644 0xcc2a, 0x1002,
645 0xcc2b, 0x2ba2,
646 0xcc2c, 0x3002,
647 0xcc2d, 0x1002,
648 0xcc2e, 0x5ee3,
649 0xcc2f, 0x305,
650 0xcc30, 0x400e,
651 0xcc31, 0x2bc2,
652 0xcc32, 0x3002,
653 0xcc33, 0x1002,
654 0xcc34, 0x2b82,
655 0xcc35, 0x3012,
656 0xcc36, 0x1002,
657 0xcc37, 0x5663,
658 0xcc38, 0x302,
659 0xcc39, 0x401e,
660 0xcc3a, 0x6f72,
661 0xcc3b, 0x1002,
662 0xcc3c, 0x628f,
663 0xcc3d, 0x2be2,
664 0xcc3e, 0x3012,
665 0xcc3f, 0x1002,
666 0xcc40, 0x22cd,
667 0xcc41, 0x301d,
668 0xcc42, 0x2e52,
669 0xcc43, 0x3012,
670 0xcc44, 0x1002,
671 0xcc45, 0x2522,
672 0xcc46, 0x3012,
673 0xcc47, 0x1002,
674 0xcc48, 0x2da2,
675 0xcc49, 0x3012,
676 0xcc4a, 0x1002,
677 0xcc4b, 0x2ca2,
678 0xcc4c, 0x3012,
679 0xcc4d, 0x1002,
680 0xcc4e, 0x2fa4,
681 0xcc4f, 0x3cd4,
682 0xcc50, 0x6624,
683 0xcc51, 0x410b,
684 0xcc52, 0x56b3,
685 0xcc53, 0x3c4,
686 0xcc54, 0x2fb2,
687 0xcc55, 0x3002,
688 0xcc56, 0x1002,
689 0xcc57, 0x220b,
690 0xcc58, 0x303b,
691 0xcc59, 0x56b3,
692 0xcc5a, 0x3c3,
693 0xcc5b, 0x866b,
694 0xcc5c, 0x400c,
695 0xcc5d, 0x23a2,
696 0xcc5e, 0x3012,
697 0xcc5f, 0x1002,
698 0xcc60, 0x2da2,
699 0xcc61, 0x3012,
700 0xcc62, 0x1002,
701 0xcc63, 0x2ca2,
702 0xcc64, 0x3012,
703 0xcc65, 0x1002,
704 0xcc66, 0x2fb4,
705 0xcc67, 0x3cd4,
706 0xcc68, 0x6624,
707 0xcc69, 0x56b3,
708 0xcc6a, 0x3c3,
709 0xcc6b, 0x866b,
710 0xcc6c, 0x401c,
711 0xcc6d, 0x2205,
712 0xcc6e, 0x3035,
713 0xcc6f, 0x5b53,
714 0xcc70, 0x2c52,
715 0xcc71, 0x3002,
716 0xcc72, 0x13c2,
717 0xcc73, 0x5cc3,
718 0xcc74, 0x317,
719 0xcc75, 0x2522,
720 0xcc76, 0x3012,
721 0xcc77, 0x1002,
722 0xcc78, 0x2da2,
723 0xcc79, 0x3012,
724 0xcc7a, 0x1002,
725 0xcc7b, 0x2b82,
726 0xcc7c, 0x3012,
727 0xcc7d, 0x1002,
728 0xcc7e, 0x5663,
729 0xcc7f, 0x303,
730 0xcc80, 0x401e,
731 0xcc81, 0x004,
732 0xcc82, 0x2c42,
733 0xcc83, 0x3012,
734 0xcc84, 0x1002,
735 0xcc85, 0x6f72,
736 0xcc86, 0x1002,
737 0xcc87, 0x628f,
738 0xcc88, 0x2304,
739 0xcc89, 0x3c84,
740 0xcc8a, 0x6436,
741 0xcc8b, 0xdff4,
742 0xcc8c, 0x6436,
743 0xcc8d, 0x2ff5,
744 0xcc8e, 0x3005,
745 0xcc8f, 0x8656,
746 0xcc90, 0xdfba,
747 0xcc91, 0x56a3,
748 0xcc92, 0xd05a,
749 0xcc93, 0x21c2,
750 0xcc94, 0x3012,
751 0xcc95, 0x1392,
752 0xcc96, 0xd05a,
753 0xcc97, 0x56a3,
754 0xcc98, 0xdfba,
755 0xcc99, 0x383,
756 0xcc9a, 0x6f72,
757 0xcc9b, 0x1002,
758 0xcc9c, 0x28c5,
759 0xcc9d, 0x3005,
760 0xcc9e, 0x4178,
761 0xcc9f, 0x5653,
762 0xcca0, 0x384,
763 0xcca1, 0x22b2,
764 0xcca2, 0x3012,
765 0xcca3, 0x1002,
766 0xcca4, 0x2be5,
767 0xcca5, 0x3005,
768 0xcca6, 0x41e8,
769 0xcca7, 0x5653,
770 0xcca8, 0x382,
771 0xcca9, 0x002,
772 0xccaa, 0x4258,
773 0xccab, 0x2474,
774 0xccac, 0x3c84,
775 0xccad, 0x6437,
776 0xccae, 0xdff4,
777 0xccaf, 0x6437,
778 0xccb0, 0x2ff5,
779 0xccb1, 0x3c05,
780 0xccb2, 0x8757,
781 0xccb3, 0xb888,
782 0xccb4, 0x9787,
783 0xccb5, 0xdff4,
784 0xccb6, 0x6724,
785 0xccb7, 0x866a,
786 0xccb8, 0x6f72,
787 0xccb9, 0x1002,
788 0xccba, 0x2d01,
789 0xccbb, 0x3011,
790 0xccbc, 0x1001,
791 0xccbd, 0xc620,
792 0xccbe, 0x14e5,
793 0xccbf, 0xc621,
794 0xccc0, 0xc53d,
795 0xccc1, 0xc622,
796 0xccc2, 0x3cbe,
797 0xccc3, 0xc623,
798 0xccc4, 0x4452,
799 0xccc5, 0xc624,
800 0xccc6, 0xc5c5,
801 0xccc7, 0xc625,
802 0xccc8, 0xe01e,
803 0xccc9, 0xc627,
804 0xccca, 0x000,
805 0xcccb, 0xc628,
806 0xcccc, 0x000,
807 0xcccd, 0xc62b,
808 0xccce, 0x000,
809 0xcccf, 0xc62c,
810 0xccd0, 0x000,
811 0xccd1, 0x000,
812 0xccd2, 0x2d01,
813 0xccd3, 0x3011,
814 0xccd4, 0x1001,
815 0xccd5, 0xc620,
816 0xccd6, 0x000,
817 0xccd7, 0xc621,
818 0xccd8, 0x000,
819 0xccd9, 0xc622,
820 0xccda, 0x0ce,
821 0xccdb, 0xc623,
822 0xccdc, 0x07f,
823 0xccdd, 0xc624,
824 0xccde, 0x032,
825 0xccdf, 0xc625,
826 0xcce0, 0x000,
827 0xcce1, 0xc627,
828 0xcce2, 0x000,
829 0xcce3, 0xc628,
830 0xcce4, 0x000,
831 0xcce5, 0xc62b,
832 0xcce6, 0x000,
833 0xcce7, 0xc62c,
834 0xcce8, 0x000,
835 0xcce9, 0x000,
836 0xccea, 0x2d01,
837 0xcceb, 0x3011,
838 0xccec, 0x1001,
839 0xcced, 0xc502,
840 0xccee, 0x609f,
841 0xccef, 0xc600,
842 0xccf0, 0x2a6e,
843 0xccf1, 0xc601,
844 0xccf2, 0x2a2c,
845 0xccf3, 0xc60c,
846 0xccf4, 0x5400,
847 0xccf5, 0xc710,
848 0xccf6, 0x700,
849 0xccf7, 0xc718,
850 0xccf8, 0x700,
851 0xccf9, 0xc720,
852 0xccfa, 0x4700,
853 0xccfb, 0xc728,
854 0xccfc, 0x700,
855 0xccfd, 0xc729,
856 0xccfe, 0x1207,
857 0xccff, 0xc801,
858 0xcd00, 0x7f50,
859 0xcd01, 0xc802,
860 0xcd02, 0x7760,
861 0xcd03, 0xc803,
862 0xcd04, 0x7fce,
863 0xcd05, 0xc804,
864 0xcd06, 0x520e,
865 0xcd07, 0xc805,
866 0xcd08, 0x5c11,
867 0xcd09, 0xc806,
868 0xcd0a, 0x3c51,
869 0xcd0b, 0xc807,
870 0xcd0c, 0x4061,
871 0xcd0d, 0xc808,
872 0xcd0e, 0x49c1,
873 0xcd0f, 0xc809,
874 0xcd10, 0x3840,
875 0xcd11, 0xc80a,
876 0xcd12, 0x000,
877 0xcd13, 0xc821,
878 0xcd14, 0x002,
879 0xcd15, 0xc822,
880 0xcd16, 0x046,
881 0xcd17, 0xc844,
882 0xcd18, 0x182f,
883 0xcd19, 0xc013,
884 0xcd1a, 0xf341,
885 0xcd1b, 0xc01a,
886 0xcd1c, 0x446,
887 0xcd1d, 0xc024,
888 0xcd1e, 0x1000,
889 0xcd1f, 0xc025,
890 0xcd20, 0xa00,
891 0xcd21, 0xc026,
892 0xcd22, 0xc0c,
893 0xcd23, 0xc027,
894 0xcd24, 0xc0c,
895 0xcd25, 0xc029,
896 0xcd26, 0x0a0,
897 0xcd27, 0xc030,
898 0xcd28, 0xa00,
899 0xcd29, 0xc03c,
900 0xcd2a, 0x01c,
901 0xcd2b, 0x000,
902 0xcd2c, 0x2b84,
903 0xcd2d, 0x3c74,
904 0xcd2e, 0x6435,
905 0xcd2f, 0xdff4,
906 0xcd30, 0x6435,
907 0xcd31, 0x2806,
908 0xcd32, 0x3006,
909 0xcd33, 0x8565,
910 0xcd34, 0x2b24,
911 0xcd35, 0x3c24,
912 0xcd36, 0x6436,
913 0xcd37, 0x1002,
914 0xcd38, 0x2b24,
915 0xcd39, 0x3c24,
916 0xcd3a, 0x6436,
917 0xcd3b, 0x4045,
918 0xcd3c, 0x8656,
919 0xcd3d, 0x1002,
920 0xcd3e, 0x2807,
921 0xcd3f, 0x31a7,
922 0xcd40, 0x20c4,
923 0xcd41, 0x3c24,
924 0xcd42, 0x6724,
925 0xcd43, 0x1002,
926 0xcd44, 0x2807,
927 0xcd45, 0x3187,
928 0xcd46, 0x20c4,
929 0xcd47, 0x3c24,
930 0xcd48, 0x6724,
931 0xcd49, 0x1002,
932 0xcd4a, 0x2514,
933 0xcd4b, 0x3c64,
934 0xcd4c, 0x6436,
935 0xcd4d, 0xdff4,
936 0xcd4e, 0x6436,
937 0xcd4f, 0x1002,
938 0xcd50, 0x2806,
939 0xcd51, 0x3cb6,
940 0xcd52, 0xc161,
941 0xcd53, 0x6134,
942 0xcd54, 0x6135,
943 0xcd55, 0x5443,
944 0xcd56, 0x303,
945 0xcd57, 0x6524,
946 0xcd58, 0x00b,
947 0xcd59, 0x1002,
948 0xcd5a, 0xd019,
949 0xcd5b, 0x2104,
950 0xcd5c, 0x3c24,
951 0xcd5d, 0x2105,
952 0xcd5e, 0x3805,
953 0xcd5f, 0x6524,
954 0xcd60, 0xdff4,
955 0xcd61, 0x4005,
956 0xcd62, 0x6524,
957 0xcd63, 0x2e8d,
958 0xcd64, 0x303d,
959 0xcd65, 0x5dd3,
960 0xcd66, 0x306,
961 0xcd67, 0x2ff7,
962 0xcd68, 0x38f7,
963 0xcd69, 0x60b7,
964 0xcd6a, 0xdffd,
965 0xcd6b, 0x00a,
966 0xcd6c, 0x1002,
967 0xcd6d, 0
968 };
969 int i, err;
970
971 err = set_phy_regs(phy, regs);
972 if (!err && modtype == phy_modtype_twinax_long)
973 err = set_phy_regs(phy, preemphasis);
974 if (err)
975 return err;
976
977 msleep(50);
978
979 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000980 err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, twinax_edc[i],
981 twinax_edc[i + 1]);
Divy Le Ray1e882022008-10-08 17:40:07 -0700982 if (!err)
983 phy->priv = edc_twinax;
984 return err;
985}
986
Divy Le Ray74451422009-05-29 12:52:44 +0000987static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
Divy Le Ray1e882022008-10-08 17:40:07 -0700988{
989 int v;
990 unsigned int stat;
991
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000992 v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, &stat);
Divy Le Ray1e882022008-10-08 17:40:07 -0700993 if (v)
994 return v;
995
996 if (stat & (1 << 8)) /* module absent */
997 return phy_modtype_none;
998
Divy Le Ray74451422009-05-29 12:52:44 +0000999 return ael2xxx_get_module_type(phy, delay_ms);
Divy Le Ray1e882022008-10-08 17:40:07 -07001000}
1001
1002static int ael2005_intr_enable(struct cphy *phy)
1003{
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001004 int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x200);
Divy Le Ray1e882022008-10-08 17:40:07 -07001005 return err ? err : t3_phy_lasi_intr_enable(phy);
1006}
1007
1008static int ael2005_intr_disable(struct cphy *phy)
1009{
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001010 int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x100);
Divy Le Ray1e882022008-10-08 17:40:07 -07001011 return err ? err : t3_phy_lasi_intr_disable(phy);
1012}
1013
1014static int ael2005_intr_clear(struct cphy *phy)
1015{
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001016 int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0xd00);
Divy Le Ray1e882022008-10-08 17:40:07 -07001017 return err ? err : t3_phy_lasi_intr_clear(phy);
1018}
1019
1020static int ael2005_reset(struct cphy *phy, int wait)
1021{
1022 static struct reg_val regs0[] = {
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001023 { MDIO_MMD_PMAPMD, 0xc001, 0, 1 << 5 },
1024 { MDIO_MMD_PMAPMD, 0xc017, 0, 1 << 5 },
1025 { MDIO_MMD_PMAPMD, 0xc013, 0xffff, 0xf341 },
1026 { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
1027 { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8100 },
1028 { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
1029 { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0 },
Divy Le Ray1e882022008-10-08 17:40:07 -07001030 { 0, 0, 0, 0 }
1031 };
1032 static struct reg_val regs1[] = {
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001033 { MDIO_MMD_PMAPMD, 0xca00, 0xffff, 0x0080 },
1034 { MDIO_MMD_PMAPMD, 0xca12, 0xffff, 0 },
Divy Le Ray1e882022008-10-08 17:40:07 -07001035 { 0, 0, 0, 0 }
1036 };
1037
Hannes Edera243f842009-02-14 11:16:19 +00001038 int err;
1039 unsigned int lasi_ctrl;
Divy Le Ray1e882022008-10-08 17:40:07 -07001040
Ben Hutchings64318332009-05-19 13:22:30 +00001041 err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
1042 &lasi_ctrl);
Divy Le Ray1e882022008-10-08 17:40:07 -07001043 if (err)
1044 return err;
1045
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001046 err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 0);
Divy Le Ray1e882022008-10-08 17:40:07 -07001047 if (err)
1048 return err;
1049
1050 msleep(125);
1051 phy->priv = edc_none;
1052 err = set_phy_regs(phy, regs0);
1053 if (err)
1054 return err;
1055
1056 msleep(50);
1057
Divy Le Ray74451422009-05-29 12:52:44 +00001058 err = ael2005_get_module_type(phy, 0);
Divy Le Ray1e882022008-10-08 17:40:07 -07001059 if (err < 0)
1060 return err;
1061 phy->modtype = err;
1062
1063 if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1064 err = ael2005_setup_twinax_edc(phy, err);
1065 else
1066 err = ael2005_setup_sr_edc(phy);
1067 if (err)
1068 return err;
1069
1070 err = set_phy_regs(phy, regs1);
1071 if (err)
1072 return err;
1073
1074 /* reset wipes out interrupts, reenable them if they were on */
1075 if (lasi_ctrl & 1)
1076 err = ael2005_intr_enable(phy);
1077 return err;
1078}
1079
1080static int ael2005_intr_handler(struct cphy *phy)
1081{
1082 unsigned int stat;
1083 int ret, edc_needed, cause = 0;
1084
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001085 ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_STAT, &stat);
Divy Le Ray1e882022008-10-08 17:40:07 -07001086 if (ret)
1087 return ret;
1088
1089 if (stat & AEL2005_MODDET_IRQ) {
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001090 ret = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL,
1091 0xd00);
Divy Le Ray1e882022008-10-08 17:40:07 -07001092 if (ret)
1093 return ret;
1094
1095 /* modules have max 300 ms init time after hot plug */
Divy Le Ray74451422009-05-29 12:52:44 +00001096 ret = ael2005_get_module_type(phy, 300);
Divy Le Ray1e882022008-10-08 17:40:07 -07001097 if (ret < 0)
1098 return ret;
1099
1100 phy->modtype = ret;
1101 if (ret == phy_modtype_none)
1102 edc_needed = phy->priv; /* on unplug retain EDC */
1103 else if (ret == phy_modtype_twinax ||
1104 ret == phy_modtype_twinax_long)
1105 edc_needed = edc_twinax;
1106 else
1107 edc_needed = edc_sr;
1108
1109 if (edc_needed != phy->priv) {
1110 ret = ael2005_reset(phy, 0);
1111 return ret ? ret : cphy_cause_module_change;
1112 }
1113 cause = cphy_cause_module_change;
1114 }
1115
1116 ret = t3_phy_lasi_intr_handler(phy);
1117 if (ret < 0)
1118 return ret;
1119
1120 ret |= cause;
1121 return ret ? ret : cphy_cause_link_change;
1122}
1123
1124static struct cphy_ops ael2005_ops = {
1125 .reset = ael2005_reset,
1126 .intr_enable = ael2005_intr_enable,
1127 .intr_disable = ael2005_intr_disable,
1128 .intr_clear = ael2005_intr_clear,
1129 .intr_handler = ael2005_intr_handler,
1130 .get_link_status = get_link_status_r,
1131 .power_down = ael1002_power_down,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001132 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
Divy Le Ray1e882022008-10-08 17:40:07 -07001133};
1134
1135int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter,
1136 int phy_addr, const struct mdio_ops *mdio_ops)
1137{
1138 cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
1139 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1140 SUPPORTED_IRQ, "10GBASE-R");
1141 msleep(125);
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001142 return t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL_OPT_SETTINGS, 0,
Divy Le Ray1e882022008-10-08 17:40:07 -07001143 1 << 5);
1144}
1145
1146/*
Divy Le Ray74451422009-05-29 12:52:44 +00001147 * Setup EDC and other parameters for operation with an optical module.
1148 */
1149static int ael2020_setup_sr_edc(struct cphy *phy)
1150{
1151 static struct reg_val regs[] = {
1152 /* set CDR offset to 10 */
1153 { MDIO_MMD_PMAPMD, 0xcc01, 0xffff, 0x488a },
1154
1155 /* adjust 10G RX bias current */
1156 { MDIO_MMD_PMAPMD, 0xcb1b, 0xffff, 0x0200 },
1157 { MDIO_MMD_PMAPMD, 0xcb1c, 0xffff, 0x00f0 },
1158 { MDIO_MMD_PMAPMD, 0xcc06, 0xffff, 0x00e0 },
1159
1160 /* end */
1161 { 0, 0, 0, 0 }
1162 };
1163 int err;
1164
1165 err = set_phy_regs(phy, regs);
1166 msleep(50);
1167 if (err)
1168 return err;
1169
1170 phy->priv = edc_sr;
1171 return 0;
1172}
1173
1174/*
1175 * Setup EDC and other parameters for operation with an TWINAX module.
1176 */
1177static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype)
1178{
1179 /* set uC to 40MHz */
1180 static struct reg_val uCclock40MHz[] = {
1181 { MDIO_MMD_PMAPMD, 0xff28, 0xffff, 0x4001 },
1182 { MDIO_MMD_PMAPMD, 0xff2a, 0xffff, 0x0002 },
1183 { 0, 0, 0, 0 }
1184 };
1185
1186 /* activate uC clock */
1187 static struct reg_val uCclockActivate[] = {
1188 { MDIO_MMD_PMAPMD, 0xd000, 0xffff, 0x5200 },
1189 { 0, 0, 0, 0 }
1190 };
1191
1192 /* set PC to start of SRAM and activate uC */
1193 static struct reg_val uCactivate[] = {
1194 { MDIO_MMD_PMAPMD, 0xd080, 0xffff, 0x0100 },
1195 { MDIO_MMD_PMAPMD, 0xd092, 0xffff, 0x0000 },
1196 { 0, 0, 0, 0 }
1197 };
1198
1199 /* TWINAX EDC firmware */
1200 static u16 twinax_edc[] = {
1201 0xd800, 0x4009,
1202 0xd801, 0x2fff,
1203 0xd802, 0x300f,
1204 0xd803, 0x40aa,
1205 0xd804, 0x401c,
1206 0xd805, 0x401e,
1207 0xd806, 0x2ff4,
1208 0xd807, 0x3dc4,
1209 0xd808, 0x2035,
1210 0xd809, 0x3035,
1211 0xd80a, 0x6524,
1212 0xd80b, 0x2cb2,
1213 0xd80c, 0x3012,
1214 0xd80d, 0x1002,
1215 0xd80e, 0x26e2,
1216 0xd80f, 0x3022,
1217 0xd810, 0x1002,
1218 0xd811, 0x27d2,
1219 0xd812, 0x3022,
1220 0xd813, 0x1002,
1221 0xd814, 0x2822,
1222 0xd815, 0x3012,
1223 0xd816, 0x1002,
1224 0xd817, 0x2492,
1225 0xd818, 0x3022,
1226 0xd819, 0x1002,
1227 0xd81a, 0x2772,
1228 0xd81b, 0x3012,
1229 0xd81c, 0x1002,
1230 0xd81d, 0x23d2,
1231 0xd81e, 0x3022,
1232 0xd81f, 0x1002,
1233 0xd820, 0x22cd,
1234 0xd821, 0x301d,
1235 0xd822, 0x27f2,
1236 0xd823, 0x3022,
1237 0xd824, 0x1002,
1238 0xd825, 0x5553,
1239 0xd826, 0x0307,
1240 0xd827, 0x2522,
1241 0xd828, 0x3022,
1242 0xd829, 0x1002,
1243 0xd82a, 0x2142,
1244 0xd82b, 0x3012,
1245 0xd82c, 0x1002,
1246 0xd82d, 0x4016,
1247 0xd82e, 0x5e63,
1248 0xd82f, 0x0344,
1249 0xd830, 0x2142,
1250 0xd831, 0x3012,
1251 0xd832, 0x1002,
1252 0xd833, 0x400e,
1253 0xd834, 0x2522,
1254 0xd835, 0x3022,
1255 0xd836, 0x1002,
1256 0xd837, 0x2b52,
1257 0xd838, 0x3012,
1258 0xd839, 0x1002,
1259 0xd83a, 0x2742,
1260 0xd83b, 0x3022,
1261 0xd83c, 0x1002,
1262 0xd83d, 0x25e2,
1263 0xd83e, 0x3022,
1264 0xd83f, 0x1002,
1265 0xd840, 0x2fa4,
1266 0xd841, 0x3dc4,
1267 0xd842, 0x6624,
1268 0xd843, 0x414b,
1269 0xd844, 0x56b3,
1270 0xd845, 0x03c6,
1271 0xd846, 0x866b,
1272 0xd847, 0x400c,
1273 0xd848, 0x2712,
1274 0xd849, 0x3012,
1275 0xd84a, 0x1002,
1276 0xd84b, 0x2c4b,
1277 0xd84c, 0x309b,
1278 0xd84d, 0x56b3,
1279 0xd84e, 0x03c3,
1280 0xd84f, 0x866b,
1281 0xd850, 0x400c,
1282 0xd851, 0x2272,
1283 0xd852, 0x3022,
1284 0xd853, 0x1002,
1285 0xd854, 0x2742,
1286 0xd855, 0x3022,
1287 0xd856, 0x1002,
1288 0xd857, 0x25e2,
1289 0xd858, 0x3022,
1290 0xd859, 0x1002,
1291 0xd85a, 0x2fb4,
1292 0xd85b, 0x3dc4,
1293 0xd85c, 0x6624,
1294 0xd85d, 0x56b3,
1295 0xd85e, 0x03c3,
1296 0xd85f, 0x866b,
1297 0xd860, 0x401c,
1298 0xd861, 0x2c45,
1299 0xd862, 0x3095,
1300 0xd863, 0x5b53,
1301 0xd864, 0x2372,
1302 0xd865, 0x3012,
1303 0xd866, 0x13c2,
1304 0xd867, 0x5cc3,
1305 0xd868, 0x2712,
1306 0xd869, 0x3012,
1307 0xd86a, 0x1312,
1308 0xd86b, 0x2b52,
1309 0xd86c, 0x3012,
1310 0xd86d, 0x1002,
1311 0xd86e, 0x2742,
1312 0xd86f, 0x3022,
1313 0xd870, 0x1002,
1314 0xd871, 0x2582,
1315 0xd872, 0x3022,
1316 0xd873, 0x1002,
1317 0xd874, 0x2142,
1318 0xd875, 0x3012,
1319 0xd876, 0x1002,
1320 0xd877, 0x628f,
1321 0xd878, 0x2985,
1322 0xd879, 0x33a5,
1323 0xd87a, 0x25e2,
1324 0xd87b, 0x3022,
1325 0xd87c, 0x1002,
1326 0xd87d, 0x5653,
1327 0xd87e, 0x03d2,
1328 0xd87f, 0x401e,
1329 0xd880, 0x6f72,
1330 0xd881, 0x1002,
1331 0xd882, 0x628f,
1332 0xd883, 0x2304,
1333 0xd884, 0x3c84,
1334 0xd885, 0x6436,
1335 0xd886, 0xdff4,
1336 0xd887, 0x6436,
1337 0xd888, 0x2ff5,
1338 0xd889, 0x3005,
1339 0xd88a, 0x8656,
1340 0xd88b, 0xdfba,
1341 0xd88c, 0x56a3,
1342 0xd88d, 0xd05a,
1343 0xd88e, 0x2972,
1344 0xd88f, 0x3012,
1345 0xd890, 0x1392,
1346 0xd891, 0xd05a,
1347 0xd892, 0x56a3,
1348 0xd893, 0xdfba,
1349 0xd894, 0x0383,
1350 0xd895, 0x6f72,
1351 0xd896, 0x1002,
1352 0xd897, 0x2b45,
1353 0xd898, 0x3005,
1354 0xd899, 0x4178,
1355 0xd89a, 0x5653,
1356 0xd89b, 0x0384,
1357 0xd89c, 0x2a62,
1358 0xd89d, 0x3012,
1359 0xd89e, 0x1002,
1360 0xd89f, 0x2f05,
1361 0xd8a0, 0x3005,
1362 0xd8a1, 0x41c8,
1363 0xd8a2, 0x5653,
1364 0xd8a3, 0x0382,
1365 0xd8a4, 0x0002,
1366 0xd8a5, 0x4218,
1367 0xd8a6, 0x2474,
1368 0xd8a7, 0x3c84,
1369 0xd8a8, 0x6437,
1370 0xd8a9, 0xdff4,
1371 0xd8aa, 0x6437,
1372 0xd8ab, 0x2ff5,
1373 0xd8ac, 0x3c05,
1374 0xd8ad, 0x8757,
1375 0xd8ae, 0xb888,
1376 0xd8af, 0x9787,
1377 0xd8b0, 0xdff4,
1378 0xd8b1, 0x6724,
1379 0xd8b2, 0x866a,
1380 0xd8b3, 0x6f72,
1381 0xd8b4, 0x1002,
1382 0xd8b5, 0x2641,
1383 0xd8b6, 0x3021,
1384 0xd8b7, 0x1001,
1385 0xd8b8, 0xc620,
1386 0xd8b9, 0x0000,
1387 0xd8ba, 0xc621,
1388 0xd8bb, 0x0000,
1389 0xd8bc, 0xc622,
1390 0xd8bd, 0x00ce,
1391 0xd8be, 0xc623,
1392 0xd8bf, 0x007f,
1393 0xd8c0, 0xc624,
1394 0xd8c1, 0x0032,
1395 0xd8c2, 0xc625,
1396 0xd8c3, 0x0000,
1397 0xd8c4, 0xc627,
1398 0xd8c5, 0x0000,
1399 0xd8c6, 0xc628,
1400 0xd8c7, 0x0000,
1401 0xd8c8, 0xc62c,
1402 0xd8c9, 0x0000,
1403 0xd8ca, 0x0000,
1404 0xd8cb, 0x2641,
1405 0xd8cc, 0x3021,
1406 0xd8cd, 0x1001,
1407 0xd8ce, 0xc502,
1408 0xd8cf, 0x53ac,
1409 0xd8d0, 0xc503,
1410 0xd8d1, 0x2cd3,
1411 0xd8d2, 0xc600,
1412 0xd8d3, 0x2a6e,
1413 0xd8d4, 0xc601,
1414 0xd8d5, 0x2a2c,
1415 0xd8d6, 0xc605,
1416 0xd8d7, 0x5557,
1417 0xd8d8, 0xc60c,
1418 0xd8d9, 0x5400,
1419 0xd8da, 0xc710,
1420 0xd8db, 0x0700,
1421 0xd8dc, 0xc711,
1422 0xd8dd, 0x0f06,
1423 0xd8de, 0xc718,
1424 0xd8df, 0x0700,
1425 0xd8e0, 0xc719,
1426 0xd8e1, 0x0f06,
1427 0xd8e2, 0xc720,
1428 0xd8e3, 0x4700,
1429 0xd8e4, 0xc721,
1430 0xd8e5, 0x0f06,
1431 0xd8e6, 0xc728,
1432 0xd8e7, 0x0700,
1433 0xd8e8, 0xc729,
1434 0xd8e9, 0x1207,
1435 0xd8ea, 0xc801,
1436 0xd8eb, 0x7f50,
1437 0xd8ec, 0xc802,
1438 0xd8ed, 0x7760,
1439 0xd8ee, 0xc803,
1440 0xd8ef, 0x7fce,
1441 0xd8f0, 0xc804,
1442 0xd8f1, 0x520e,
1443 0xd8f2, 0xc805,
1444 0xd8f3, 0x5c11,
1445 0xd8f4, 0xc806,
1446 0xd8f5, 0x3c51,
1447 0xd8f6, 0xc807,
1448 0xd8f7, 0x4061,
1449 0xd8f8, 0xc808,
1450 0xd8f9, 0x49c1,
1451 0xd8fa, 0xc809,
1452 0xd8fb, 0x3840,
1453 0xd8fc, 0xc80a,
1454 0xd8fd, 0x0000,
1455 0xd8fe, 0xc821,
1456 0xd8ff, 0x0002,
1457 0xd900, 0xc822,
1458 0xd901, 0x0046,
1459 0xd902, 0xc844,
1460 0xd903, 0x182f,
1461 0xd904, 0xc013,
1462 0xd905, 0xf341,
1463 0xd906, 0xc084,
1464 0xd907, 0x0030,
1465 0xd908, 0xc904,
1466 0xd909, 0x1401,
1467 0xd90a, 0xcb0c,
1468 0xd90b, 0x0004,
1469 0xd90c, 0xcb0e,
1470 0xd90d, 0xa00a,
1471 0xd90e, 0xcb0f,
1472 0xd90f, 0xc0c0,
1473 0xd910, 0xcb10,
1474 0xd911, 0xc0c0,
1475 0xd912, 0xcb11,
1476 0xd913, 0x00a0,
1477 0xd914, 0xcb12,
1478 0xd915, 0x0007,
1479 0xd916, 0xc241,
1480 0xd917, 0xa000,
1481 0xd918, 0xc243,
1482 0xd919, 0x7fe0,
1483 0xd91a, 0xc604,
1484 0xd91b, 0x000e,
1485 0xd91c, 0xc609,
1486 0xd91d, 0x00f5,
1487 0xd91e, 0xc611,
1488 0xd91f, 0x000e,
1489 0xd920, 0xc660,
1490 0xd921, 0x9600,
1491 0xd922, 0xc687,
1492 0xd923, 0x0004,
1493 0xd924, 0xc60a,
1494 0xd925, 0x04f5,
1495 0xd926, 0x0000,
1496 0xd927, 0x2641,
1497 0xd928, 0x3021,
1498 0xd929, 0x1001,
1499 0xd92a, 0xc620,
1500 0xd92b, 0x14e5,
1501 0xd92c, 0xc621,
1502 0xd92d, 0xc53d,
1503 0xd92e, 0xc622,
1504 0xd92f, 0x3cbe,
1505 0xd930, 0xc623,
1506 0xd931, 0x4452,
1507 0xd932, 0xc624,
1508 0xd933, 0xc5c5,
1509 0xd934, 0xc625,
1510 0xd935, 0xe01e,
1511 0xd936, 0xc627,
1512 0xd937, 0x0000,
1513 0xd938, 0xc628,
1514 0xd939, 0x0000,
1515 0xd93a, 0xc62c,
1516 0xd93b, 0x0000,
1517 0xd93c, 0x0000,
1518 0xd93d, 0x2b84,
1519 0xd93e, 0x3c74,
1520 0xd93f, 0x6435,
1521 0xd940, 0xdff4,
1522 0xd941, 0x6435,
1523 0xd942, 0x2806,
1524 0xd943, 0x3006,
1525 0xd944, 0x8565,
1526 0xd945, 0x2b24,
1527 0xd946, 0x3c24,
1528 0xd947, 0x6436,
1529 0xd948, 0x1002,
1530 0xd949, 0x2b24,
1531 0xd94a, 0x3c24,
1532 0xd94b, 0x6436,
1533 0xd94c, 0x4045,
1534 0xd94d, 0x8656,
1535 0xd94e, 0x5663,
1536 0xd94f, 0x0302,
1537 0xd950, 0x401e,
1538 0xd951, 0x1002,
1539 0xd952, 0x2807,
1540 0xd953, 0x31a7,
1541 0xd954, 0x20c4,
1542 0xd955, 0x3c24,
1543 0xd956, 0x6724,
1544 0xd957, 0x1002,
1545 0xd958, 0x2807,
1546 0xd959, 0x3187,
1547 0xd95a, 0x20c4,
1548 0xd95b, 0x3c24,
1549 0xd95c, 0x6724,
1550 0xd95d, 0x1002,
1551 0xd95e, 0x24f4,
1552 0xd95f, 0x3c64,
1553 0xd960, 0x6436,
1554 0xd961, 0xdff4,
1555 0xd962, 0x6436,
1556 0xd963, 0x1002,
1557 0xd964, 0x2006,
1558 0xd965, 0x3d76,
1559 0xd966, 0xc161,
1560 0xd967, 0x6134,
1561 0xd968, 0x6135,
1562 0xd969, 0x5443,
1563 0xd96a, 0x0303,
1564 0xd96b, 0x6524,
1565 0xd96c, 0x00fb,
1566 0xd96d, 0x1002,
1567 0xd96e, 0x20d4,
1568 0xd96f, 0x3c24,
1569 0xd970, 0x2025,
1570 0xd971, 0x3005,
1571 0xd972, 0x6524,
1572 0xd973, 0x1002,
1573 0xd974, 0xd019,
1574 0xd975, 0x2104,
1575 0xd976, 0x3c24,
1576 0xd977, 0x2105,
1577 0xd978, 0x3805,
1578 0xd979, 0x6524,
1579 0xd97a, 0xdff4,
1580 0xd97b, 0x4005,
1581 0xd97c, 0x6524,
1582 0xd97d, 0x2e8d,
1583 0xd97e, 0x303d,
1584 0xd97f, 0x2408,
1585 0xd980, 0x35d8,
1586 0xd981, 0x5dd3,
1587 0xd982, 0x0307,
1588 0xd983, 0x8887,
1589 0xd984, 0x63a7,
1590 0xd985, 0x8887,
1591 0xd986, 0x63a7,
1592 0xd987, 0xdffd,
1593 0xd988, 0x00f9,
1594 0xd989, 0x1002,
1595 0xd98a, 0x0000,
1596 };
1597 int i, err;
1598
1599 /* set uC clock and activate it */
1600 err = set_phy_regs(phy, uCclock40MHz);
1601 msleep(500);
1602 if (err)
1603 return err;
1604 err = set_phy_regs(phy, uCclockActivate);
1605 msleep(500);
1606 if (err)
1607 return err;
1608
1609 /* write TWINAX EDC firmware into PHY */
1610 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1611 err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, twinax_edc[i],
1612 twinax_edc[i + 1]);
1613 /* activate uC */
1614 err = set_phy_regs(phy, uCactivate);
1615 if (!err)
1616 phy->priv = edc_twinax;
1617 return err;
1618}
1619
1620/*
1621 * Return Module Type.
1622 */
1623static int ael2020_get_module_type(struct cphy *phy, int delay_ms)
1624{
1625 int v;
1626 unsigned int stat;
1627
1628 v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_STAT, &stat);
1629 if (v)
1630 return v;
1631
1632 if (stat & (0x1 << (AEL2020_GPIO_MODDET*4))) {
1633 /* module absent */
1634 return phy_modtype_none;
1635 }
1636
1637 return ael2xxx_get_module_type(phy, delay_ms);
1638}
1639
1640/*
1641 * Enable PHY interrupts. We enable "Module Detection" interrupts (on any
1642 * state transition) and then generic Link Alarm Status Interrupt (LASI).
1643 */
1644static int ael2020_intr_enable(struct cphy *phy)
1645{
Divy Le Ray5e659512009-07-07 19:48:43 +00001646 struct reg_val regs[] = {
1647 /* output Module's Loss Of Signal (LOS) to LED */
1648 { MDIO_MMD_PMAPMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT,
1649 0xffff, 0x4 },
1650 { MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
1651 0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) },
1652
1653 /* enable module detect status change interrupts */
1654 { MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
1655 0xffff, 0x2 << (AEL2020_GPIO_MODDET*4) },
1656
1657 /* end */
1658 { 0, 0, 0, 0 }
1659 };
1660 int err, link_ok = 0;
1661
1662 /* set up "link status" LED and enable module change interrupts */
1663 err = set_phy_regs(phy, regs);
1664 if (err)
1665 return err;
1666
1667 err = get_link_status_r(phy, &link_ok, NULL, NULL, NULL);
1668 if (err)
1669 return err;
1670 if (link_ok)
1671 t3_link_changed(phy->adapter,
1672 phy2portid(phy));
1673
1674 err = t3_phy_lasi_intr_enable(phy);
1675 if (err)
1676 return err;
1677
1678 return 0;
Divy Le Ray74451422009-05-29 12:52:44 +00001679}
1680
1681/*
1682 * Disable PHY interrupts. The mirror of the above ...
1683 */
1684static int ael2020_intr_disable(struct cphy *phy)
1685{
Divy Le Ray5e659512009-07-07 19:48:43 +00001686 struct reg_val regs[] = {
1687 /* reset "link status" LED to "off" */
1688 { MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
1689 0xffff, 0xb << (AEL2020_GPIO_LSTAT*4) },
1690
1691 /* disable module detect status change interrupts */
1692 { MDIO_MMD_PMAPMD, AEL2020_GPIO_CTRL,
1693 0xffff, 0x1 << (AEL2020_GPIO_MODDET*4) },
1694
1695 /* end */
1696 { 0, 0, 0, 0 }
1697 };
1698 int err;
1699
1700 /* turn off "link status" LED and disable module change interrupts */
1701 err = set_phy_regs(phy, regs);
1702 if (err)
1703 return err;
1704
1705 return t3_phy_lasi_intr_disable(phy);
Divy Le Ray74451422009-05-29 12:52:44 +00001706}
1707
1708/*
1709 * Clear PHY interrupt state.
1710 */
1711static int ael2020_intr_clear(struct cphy *phy)
1712{
1713 /*
1714 * The GPIO Interrupt register on the AEL2020 is a "Latching High"
1715 * (LH) register which is cleared to the current state when it's read.
1716 * Thus, we simply read the register and discard the result.
1717 */
1718 unsigned int stat;
1719 int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_INTR, &stat);
1720 return err ? err : t3_phy_lasi_intr_clear(phy);
1721}
1722
Divy Le Ray5e659512009-07-07 19:48:43 +00001723static struct reg_val ael2020_reset_regs[] = {
1724 /* Erratum #2: CDRLOL asserted, causing PMA link down status */
1725 { MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x3101 },
1726
1727 /* force XAUI to send LF when RX_LOS is asserted */
1728 { MDIO_MMD_PMAPMD, 0xcd40, 0xffff, 0x0001 },
1729
1730 /* allow writes to transceiver module EEPROM on i2c bus */
1731 { MDIO_MMD_PMAPMD, 0xff02, 0xffff, 0x0023 },
1732 { MDIO_MMD_PMAPMD, 0xff03, 0xffff, 0x0000 },
1733 { MDIO_MMD_PMAPMD, 0xff04, 0xffff, 0x0000 },
1734
1735 /* end */
1736 { 0, 0, 0, 0 }
1737};
Divy Le Ray74451422009-05-29 12:52:44 +00001738/*
1739 * Reset the PHY and put it into a canonical operating state.
1740 */
1741static int ael2020_reset(struct cphy *phy, int wait)
1742{
Divy Le Ray74451422009-05-29 12:52:44 +00001743 int err;
1744 unsigned int lasi_ctrl;
1745
1746 /* grab current interrupt state */
1747 err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
1748 &lasi_ctrl);
1749 if (err)
1750 return err;
1751
1752 err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 125);
1753 if (err)
1754 return err;
1755 msleep(100);
1756
1757 /* basic initialization for all module types */
1758 phy->priv = edc_none;
Divy Le Ray5e659512009-07-07 19:48:43 +00001759 err = set_phy_regs(phy, ael2020_reset_regs);
Divy Le Ray74451422009-05-29 12:52:44 +00001760 if (err)
1761 return err;
1762
1763 /* determine module type and perform appropriate initialization */
1764 err = ael2020_get_module_type(phy, 0);
1765 if (err < 0)
1766 return err;
1767 phy->modtype = (u8)err;
1768 if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1769 err = ael2020_setup_twinax_edc(phy, err);
1770 else
1771 err = ael2020_setup_sr_edc(phy);
1772 if (err)
1773 return err;
1774
1775 /* reset wipes out interrupts, reenable them if they were on */
1776 if (lasi_ctrl & 1)
1777 err = ael2005_intr_enable(phy);
1778 return err;
1779}
1780
1781/*
1782 * Handle a PHY interrupt.
1783 */
1784static int ael2020_intr_handler(struct cphy *phy)
1785{
1786 unsigned int stat;
1787 int ret, edc_needed, cause = 0;
1788
1789 ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2020_GPIO_INTR, &stat);
1790 if (ret)
1791 return ret;
1792
1793 if (stat & (0x1 << AEL2020_GPIO_MODDET)) {
1794 /* modules have max 300 ms init time after hot plug */
1795 ret = ael2020_get_module_type(phy, 300);
1796 if (ret < 0)
1797 return ret;
1798
1799 phy->modtype = (u8)ret;
1800 if (ret == phy_modtype_none)
1801 edc_needed = phy->priv; /* on unplug retain EDC */
1802 else if (ret == phy_modtype_twinax ||
1803 ret == phy_modtype_twinax_long)
1804 edc_needed = edc_twinax;
1805 else
1806 edc_needed = edc_sr;
1807
1808 if (edc_needed != phy->priv) {
1809 ret = ael2020_reset(phy, 0);
1810 return ret ? ret : cphy_cause_module_change;
1811 }
1812 cause = cphy_cause_module_change;
1813 }
1814
1815 ret = t3_phy_lasi_intr_handler(phy);
1816 if (ret < 0)
1817 return ret;
1818
1819 ret |= cause;
1820 return ret ? ret : cphy_cause_link_change;
1821}
1822
1823static struct cphy_ops ael2020_ops = {
1824 .reset = ael2020_reset,
1825 .intr_enable = ael2020_intr_enable,
1826 .intr_disable = ael2020_intr_disable,
1827 .intr_clear = ael2020_intr_clear,
1828 .intr_handler = ael2020_intr_handler,
1829 .get_link_status = get_link_status_r,
1830 .power_down = ael1002_power_down,
1831 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
1832};
1833
1834int t3_ael2020_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
1835 const struct mdio_ops *mdio_ops)
1836{
Divy Le Ray5e659512009-07-07 19:48:43 +00001837 int err;
1838
Divy Le Ray74451422009-05-29 12:52:44 +00001839 cphy_init(phy, adapter, phy_addr, &ael2020_ops, mdio_ops,
1840 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1841 SUPPORTED_IRQ, "10GBASE-R");
1842 msleep(125);
Divy Le Ray5e659512009-07-07 19:48:43 +00001843
1844 err = set_phy_regs(phy, ael2020_reset_regs);
1845 if (err)
1846 return err;
Divy Le Ray74451422009-05-29 12:52:44 +00001847 return 0;
1848}
1849
1850/*
Divy Le Ray1e882022008-10-08 17:40:07 -07001851 * Get link status for a 10GBASE-X device.
1852 */
1853static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
1854 int *duplex, int *fc)
1855{
1856 if (link_ok) {
1857 unsigned int stat0, stat1, stat2;
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001858 int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
1859 MDIO_PMA_RXDET, &stat0);
Divy Le Ray1e882022008-10-08 17:40:07 -07001860
1861 if (!err)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001862 err = t3_mdio_read(phy, MDIO_MMD_PCS,
1863 MDIO_PCS_10GBX_STAT1, &stat1);
Divy Le Ray1e882022008-10-08 17:40:07 -07001864 if (!err)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001865 err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
1866 MDIO_PHYXS_LNSTAT, &stat2);
Divy Le Ray1e882022008-10-08 17:40:07 -07001867 if (err)
1868 return err;
1869 *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
1870 }
1871 if (speed)
1872 *speed = SPEED_10000;
1873 if (duplex)
1874 *duplex = DUPLEX_FULL;
1875 return 0;
1876}
1877
Divy Le Ray4d22de32007-01-18 22:04:14 -05001878static struct cphy_ops qt2045_ops = {
1879 .reset = ael1006_reset,
Divy Le Ray9b1e3652008-10-08 17:39:31 -07001880 .intr_enable = t3_phy_lasi_intr_enable,
1881 .intr_disable = t3_phy_lasi_intr_disable,
1882 .intr_clear = t3_phy_lasi_intr_clear,
1883 .intr_handler = t3_phy_lasi_intr_handler,
Divy Le Ray1e882022008-10-08 17:40:07 -07001884 .get_link_status = get_link_status_x,
Divy Le Ray619f05c2009-07-07 19:48:53 +00001885 .power_down = ael1002_power_down,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001886 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
Divy Le Ray4d22de32007-01-18 22:04:14 -05001887};
1888
Divy Le Ray78e46892008-10-08 17:38:01 -07001889int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
1890 int phy_addr, const struct mdio_ops *mdio_ops)
Divy Le Ray4d22de32007-01-18 22:04:14 -05001891{
1892 unsigned int stat;
1893
Divy Le Ray04497982008-10-08 17:38:29 -07001894 cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops,
1895 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1896 "10GBASE-CX4");
Divy Le Ray4d22de32007-01-18 22:04:14 -05001897
1898 /*
1899 * Some cards where the PHY is supposed to be at address 0 actually
1900 * have it at 1.
1901 */
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001902 if (!phy_addr &&
1903 !t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &stat) &&
Divy Le Ray4d22de32007-01-18 22:04:14 -05001904 stat == 0xffff)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001905 phy->mdio.prtad = 1;
Divy Le Ray78e46892008-10-08 17:38:01 -07001906 return 0;
Divy Le Ray4d22de32007-01-18 22:04:14 -05001907}
1908
1909static int xaui_direct_reset(struct cphy *phy, int wait)
1910{
1911 return 0;
1912}
1913
1914static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
1915 int *speed, int *duplex, int *fc)
1916{
1917 if (link_ok) {
1918 unsigned int status;
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001919 int prtad = phy->mdio.prtad;
Divy Le Ray4d22de32007-01-18 22:04:14 -05001920
1921 status = t3_read_reg(phy->adapter,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001922 XGM_REG(A_XGM_SERDES_STAT0, prtad)) |
Divy Le Rayc706bfb2007-05-30 10:01:39 -07001923 t3_read_reg(phy->adapter,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001924 XGM_REG(A_XGM_SERDES_STAT1, prtad)) |
Divy Le Rayc706bfb2007-05-30 10:01:39 -07001925 t3_read_reg(phy->adapter,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001926 XGM_REG(A_XGM_SERDES_STAT2, prtad)) |
Divy Le Rayc706bfb2007-05-30 10:01:39 -07001927 t3_read_reg(phy->adapter,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001928 XGM_REG(A_XGM_SERDES_STAT3, prtad));
Divy Le Ray4d22de32007-01-18 22:04:14 -05001929 *link_ok = !(status & F_LOWSIG0);
1930 }
1931 if (speed)
1932 *speed = SPEED_10000;
1933 if (duplex)
1934 *duplex = DUPLEX_FULL;
1935 return 0;
1936}
1937
1938static int xaui_direct_power_down(struct cphy *phy, int enable)
1939{
1940 return 0;
1941}
1942
1943static struct cphy_ops xaui_direct_ops = {
1944 .reset = xaui_direct_reset,
1945 .intr_enable = ael1002_intr_noop,
1946 .intr_disable = ael1002_intr_noop,
1947 .intr_clear = ael1002_intr_noop,
1948 .intr_handler = ael1002_intr_noop,
1949 .get_link_status = xaui_direct_get_link_status,
1950 .power_down = xaui_direct_power_down,
1951};
1952
Divy Le Ray78e46892008-10-08 17:38:01 -07001953int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
1954 int phy_addr, const struct mdio_ops *mdio_ops)
Divy Le Ray4d22de32007-01-18 22:04:14 -05001955{
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001956 cphy_init(phy, adapter, MDIO_PRTAD_NONE, &xaui_direct_ops, mdio_ops,
Divy Le Ray04497982008-10-08 17:38:29 -07001957 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1958 "10GBASE-CX4");
Divy Le Ray78e46892008-10-08 17:38:01 -07001959 return 0;
Divy Le Ray4d22de32007-01-18 22:04:14 -05001960}