blob: 9fe008ec9ba5922f2170842fe84506e522ed0894 [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 int ael1006_power_down(struct cphy *phy, int enable)
228{
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000229 return mdio_set_flag(&phy->mdio, phy->mdio.prtad, MDIO_MMD_PMAPMD,
230 MDIO_CTRL1, MDIO_CTRL1_LPOWER, enable);
Divy Le Ray4d22de32007-01-18 22:04:14 -0500231}
232
233static struct cphy_ops ael1006_ops = {
234 .reset = ael1006_reset,
Divy Le Ray9b1e3652008-10-08 17:39:31 -0700235 .intr_enable = t3_phy_lasi_intr_enable,
236 .intr_disable = t3_phy_lasi_intr_disable,
237 .intr_clear = t3_phy_lasi_intr_clear,
238 .intr_handler = t3_phy_lasi_intr_handler,
Divy Le Ray1e882022008-10-08 17:40:07 -0700239 .get_link_status = get_link_status_r,
Divy Le Ray4d22de32007-01-18 22:04:14 -0500240 .power_down = ael1006_power_down,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000241 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
Divy Le Ray4d22de32007-01-18 22:04:14 -0500242};
243
Divy Le Ray78e46892008-10-08 17:38:01 -0700244int t3_ael1006_phy_prep(struct cphy *phy, struct adapter *adapter,
245 int phy_addr, const struct mdio_ops *mdio_ops)
Divy Le Ray4d22de32007-01-18 22:04:14 -0500246{
Divy Le Ray04497982008-10-08 17:38:29 -0700247 cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops,
248 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
249 "10GBASE-SR");
Divy Le Ray4d22de32007-01-18 22:04:14 -0500250 ael100x_txon(phy);
Divy Le Ray78e46892008-10-08 17:38:01 -0700251 return 0;
Divy Le Ray4d22de32007-01-18 22:04:14 -0500252}
253
Divy Le Ray74451422009-05-29 12:52:44 +0000254/*
255 * Decode our module type.
256 */
257static 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 }
292unknown:
293 return phy_modtype_unknown;
294}
295
296/*
297 * Code to support the Aeluros/NetLogic 2005 10Gb PHY.
298 */
Divy Le Ray1e882022008-10-08 17:40:07 -0700299static int ael2005_setup_sr_edc(struct cphy *phy)
300{
301 static struct reg_val regs[] = {
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000302 { MDIO_MMD_PMAPMD, 0xc003, 0xffff, 0x181 },
303 { MDIO_MMD_PMAPMD, 0xc010, 0xffff, 0x448a },
304 { MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5200 },
Divy Le Ray1e882022008-10-08 17:40:07 -0700305 { 0, 0, 0, 0 }
306 };
307 static u16 sr_edc[] = {
308 0xcc00, 0x2ff4,
309 0xcc01, 0x3cd4,
310 0xcc02, 0x2015,
311 0xcc03, 0x3105,
312 0xcc04, 0x6524,
313 0xcc05, 0x27ff,
314 0xcc06, 0x300f,
315 0xcc07, 0x2c8b,
316 0xcc08, 0x300b,
317 0xcc09, 0x4009,
318 0xcc0a, 0x400e,
319 0xcc0b, 0x2f72,
320 0xcc0c, 0x3002,
321 0xcc0d, 0x1002,
322 0xcc0e, 0x2172,
323 0xcc0f, 0x3012,
324 0xcc10, 0x1002,
325 0xcc11, 0x25d2,
326 0xcc12, 0x3012,
327 0xcc13, 0x1002,
328 0xcc14, 0xd01e,
329 0xcc15, 0x27d2,
330 0xcc16, 0x3012,
331 0xcc17, 0x1002,
332 0xcc18, 0x2004,
333 0xcc19, 0x3c84,
334 0xcc1a, 0x6436,
335 0xcc1b, 0x2007,
336 0xcc1c, 0x3f87,
337 0xcc1d, 0x8676,
338 0xcc1e, 0x40b7,
339 0xcc1f, 0xa746,
340 0xcc20, 0x4047,
341 0xcc21, 0x5673,
342 0xcc22, 0x2982,
343 0xcc23, 0x3002,
344 0xcc24, 0x13d2,
345 0xcc25, 0x8bbd,
346 0xcc26, 0x2862,
347 0xcc27, 0x3012,
348 0xcc28, 0x1002,
349 0xcc29, 0x2092,
350 0xcc2a, 0x3012,
351 0xcc2b, 0x1002,
352 0xcc2c, 0x5cc3,
353 0xcc2d, 0x314,
354 0xcc2e, 0x2942,
355 0xcc2f, 0x3002,
356 0xcc30, 0x1002,
357 0xcc31, 0xd019,
358 0xcc32, 0x2032,
359 0xcc33, 0x3012,
360 0xcc34, 0x1002,
361 0xcc35, 0x2a04,
362 0xcc36, 0x3c74,
363 0xcc37, 0x6435,
364 0xcc38, 0x2fa4,
365 0xcc39, 0x3cd4,
366 0xcc3a, 0x6624,
367 0xcc3b, 0x5563,
368 0xcc3c, 0x2d42,
369 0xcc3d, 0x3002,
370 0xcc3e, 0x13d2,
371 0xcc3f, 0x464d,
372 0xcc40, 0x2862,
373 0xcc41, 0x3012,
374 0xcc42, 0x1002,
375 0xcc43, 0x2032,
376 0xcc44, 0x3012,
377 0xcc45, 0x1002,
378 0xcc46, 0x2fb4,
379 0xcc47, 0x3cd4,
380 0xcc48, 0x6624,
381 0xcc49, 0x5563,
382 0xcc4a, 0x2d42,
383 0xcc4b, 0x3002,
384 0xcc4c, 0x13d2,
385 0xcc4d, 0x2ed2,
386 0xcc4e, 0x3002,
387 0xcc4f, 0x1002,
388 0xcc50, 0x2fd2,
389 0xcc51, 0x3002,
390 0xcc52, 0x1002,
391 0xcc53, 0x004,
392 0xcc54, 0x2942,
393 0xcc55, 0x3002,
394 0xcc56, 0x1002,
395 0xcc57, 0x2092,
396 0xcc58, 0x3012,
397 0xcc59, 0x1002,
398 0xcc5a, 0x5cc3,
399 0xcc5b, 0x317,
400 0xcc5c, 0x2f72,
401 0xcc5d, 0x3002,
402 0xcc5e, 0x1002,
403 0xcc5f, 0x2942,
404 0xcc60, 0x3002,
405 0xcc61, 0x1002,
406 0xcc62, 0x22cd,
407 0xcc63, 0x301d,
408 0xcc64, 0x2862,
409 0xcc65, 0x3012,
410 0xcc66, 0x1002,
411 0xcc67, 0x2ed2,
412 0xcc68, 0x3002,
413 0xcc69, 0x1002,
414 0xcc6a, 0x2d72,
415 0xcc6b, 0x3002,
416 0xcc6c, 0x1002,
417 0xcc6d, 0x628f,
418 0xcc6e, 0x2112,
419 0xcc6f, 0x3012,
420 0xcc70, 0x1002,
421 0xcc71, 0x5aa3,
422 0xcc72, 0x2dc2,
423 0xcc73, 0x3002,
424 0xcc74, 0x1312,
425 0xcc75, 0x6f72,
426 0xcc76, 0x1002,
427 0xcc77, 0x2807,
428 0xcc78, 0x31a7,
429 0xcc79, 0x20c4,
430 0xcc7a, 0x3c24,
431 0xcc7b, 0x6724,
432 0xcc7c, 0x1002,
433 0xcc7d, 0x2807,
434 0xcc7e, 0x3187,
435 0xcc7f, 0x20c4,
436 0xcc80, 0x3c24,
437 0xcc81, 0x6724,
438 0xcc82, 0x1002,
439 0xcc83, 0x2514,
440 0xcc84, 0x3c64,
441 0xcc85, 0x6436,
442 0xcc86, 0xdff4,
443 0xcc87, 0x6436,
444 0xcc88, 0x1002,
445 0xcc89, 0x40a4,
446 0xcc8a, 0x643c,
447 0xcc8b, 0x4016,
448 0xcc8c, 0x8c6c,
449 0xcc8d, 0x2b24,
450 0xcc8e, 0x3c24,
451 0xcc8f, 0x6435,
452 0xcc90, 0x1002,
453 0xcc91, 0x2b24,
454 0xcc92, 0x3c24,
455 0xcc93, 0x643a,
456 0xcc94, 0x4025,
457 0xcc95, 0x8a5a,
458 0xcc96, 0x1002,
459 0xcc97, 0x2731,
460 0xcc98, 0x3011,
461 0xcc99, 0x1001,
462 0xcc9a, 0xc7a0,
463 0xcc9b, 0x100,
464 0xcc9c, 0xc502,
465 0xcc9d, 0x53ac,
466 0xcc9e, 0xc503,
467 0xcc9f, 0xd5d5,
468 0xcca0, 0xc600,
469 0xcca1, 0x2a6d,
470 0xcca2, 0xc601,
471 0xcca3, 0x2a4c,
472 0xcca4, 0xc602,
473 0xcca5, 0x111,
474 0xcca6, 0xc60c,
475 0xcca7, 0x5900,
476 0xcca8, 0xc710,
477 0xcca9, 0x700,
478 0xccaa, 0xc718,
479 0xccab, 0x700,
480 0xccac, 0xc720,
481 0xccad, 0x4700,
482 0xccae, 0xc801,
483 0xccaf, 0x7f50,
484 0xccb0, 0xc802,
485 0xccb1, 0x7760,
486 0xccb2, 0xc803,
487 0xccb3, 0x7fce,
488 0xccb4, 0xc804,
489 0xccb5, 0x5700,
490 0xccb6, 0xc805,
491 0xccb7, 0x5f11,
492 0xccb8, 0xc806,
493 0xccb9, 0x4751,
494 0xccba, 0xc807,
495 0xccbb, 0x57e1,
496 0xccbc, 0xc808,
497 0xccbd, 0x2700,
498 0xccbe, 0xc809,
499 0xccbf, 0x000,
500 0xccc0, 0xc821,
501 0xccc1, 0x002,
502 0xccc2, 0xc822,
503 0xccc3, 0x014,
504 0xccc4, 0xc832,
505 0xccc5, 0x1186,
506 0xccc6, 0xc847,
507 0xccc7, 0x1e02,
508 0xccc8, 0xc013,
509 0xccc9, 0xf341,
510 0xccca, 0xc01a,
511 0xcccb, 0x446,
512 0xcccc, 0xc024,
513 0xcccd, 0x1000,
514 0xccce, 0xc025,
515 0xcccf, 0xa00,
516 0xccd0, 0xc026,
517 0xccd1, 0xc0c,
518 0xccd2, 0xc027,
519 0xccd3, 0xc0c,
520 0xccd4, 0xc029,
521 0xccd5, 0x0a0,
522 0xccd6, 0xc030,
523 0xccd7, 0xa00,
524 0xccd8, 0xc03c,
525 0xccd9, 0x01c,
526 0xccda, 0xc005,
527 0xccdb, 0x7a06,
528 0xccdc, 0x000,
529 0xccdd, 0x2731,
530 0xccde, 0x3011,
531 0xccdf, 0x1001,
532 0xcce0, 0xc620,
533 0xcce1, 0x000,
534 0xcce2, 0xc621,
535 0xcce3, 0x03f,
536 0xcce4, 0xc622,
537 0xcce5, 0x000,
538 0xcce6, 0xc623,
539 0xcce7, 0x000,
540 0xcce8, 0xc624,
541 0xcce9, 0x000,
542 0xccea, 0xc625,
543 0xcceb, 0x000,
544 0xccec, 0xc627,
545 0xcced, 0x000,
546 0xccee, 0xc628,
547 0xccef, 0x000,
548 0xccf0, 0xc62c,
549 0xccf1, 0x000,
550 0xccf2, 0x000,
551 0xccf3, 0x2806,
552 0xccf4, 0x3cb6,
553 0xccf5, 0xc161,
554 0xccf6, 0x6134,
555 0xccf7, 0x6135,
556 0xccf8, 0x5443,
557 0xccf9, 0x303,
558 0xccfa, 0x6524,
559 0xccfb, 0x00b,
560 0xccfc, 0x1002,
561 0xccfd, 0x2104,
562 0xccfe, 0x3c24,
563 0xccff, 0x2105,
564 0xcd00, 0x3805,
565 0xcd01, 0x6524,
566 0xcd02, 0xdff4,
567 0xcd03, 0x4005,
568 0xcd04, 0x6524,
569 0xcd05, 0x1002,
570 0xcd06, 0x5dd3,
571 0xcd07, 0x306,
572 0xcd08, 0x2ff7,
573 0xcd09, 0x38f7,
574 0xcd0a, 0x60b7,
575 0xcd0b, 0xdffd,
576 0xcd0c, 0x00a,
577 0xcd0d, 0x1002,
578 0xcd0e, 0
579 };
580 int i, err;
581
582 err = set_phy_regs(phy, regs);
583 if (err)
584 return err;
585
586 msleep(50);
587
588 for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000589 err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, sr_edc[i],
590 sr_edc[i + 1]);
Divy Le Ray1e882022008-10-08 17:40:07 -0700591 if (!err)
592 phy->priv = edc_sr;
593 return err;
594}
595
596static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
597{
598 static struct reg_val regs[] = {
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000599 { MDIO_MMD_PMAPMD, 0xc04a, 0xffff, 0x5a00 },
Divy Le Ray1e882022008-10-08 17:40:07 -0700600 { 0, 0, 0, 0 }
601 };
602 static struct reg_val preemphasis[] = {
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000603 { MDIO_MMD_PMAPMD, 0xc014, 0xffff, 0xfe16 },
604 { MDIO_MMD_PMAPMD, 0xc015, 0xffff, 0xa000 },
Divy Le Ray1e882022008-10-08 17:40:07 -0700605 { 0, 0, 0, 0 }
606 };
607 static u16 twinax_edc[] = {
608 0xcc00, 0x4009,
609 0xcc01, 0x27ff,
610 0xcc02, 0x300f,
611 0xcc03, 0x40aa,
612 0xcc04, 0x401c,
613 0xcc05, 0x401e,
614 0xcc06, 0x2ff4,
615 0xcc07, 0x3cd4,
616 0xcc08, 0x2035,
617 0xcc09, 0x3145,
618 0xcc0a, 0x6524,
619 0xcc0b, 0x26a2,
620 0xcc0c, 0x3012,
621 0xcc0d, 0x1002,
622 0xcc0e, 0x29c2,
623 0xcc0f, 0x3002,
624 0xcc10, 0x1002,
625 0xcc11, 0x2072,
626 0xcc12, 0x3012,
627 0xcc13, 0x1002,
628 0xcc14, 0x22cd,
629 0xcc15, 0x301d,
630 0xcc16, 0x2e52,
631 0xcc17, 0x3012,
632 0xcc18, 0x1002,
633 0xcc19, 0x28e2,
634 0xcc1a, 0x3002,
635 0xcc1b, 0x1002,
636 0xcc1c, 0x628f,
637 0xcc1d, 0x2ac2,
638 0xcc1e, 0x3012,
639 0xcc1f, 0x1002,
640 0xcc20, 0x5553,
641 0xcc21, 0x2ae2,
642 0xcc22, 0x3002,
643 0xcc23, 0x1302,
644 0xcc24, 0x401e,
645 0xcc25, 0x2be2,
646 0xcc26, 0x3012,
647 0xcc27, 0x1002,
648 0xcc28, 0x2da2,
649 0xcc29, 0x3012,
650 0xcc2a, 0x1002,
651 0xcc2b, 0x2ba2,
652 0xcc2c, 0x3002,
653 0xcc2d, 0x1002,
654 0xcc2e, 0x5ee3,
655 0xcc2f, 0x305,
656 0xcc30, 0x400e,
657 0xcc31, 0x2bc2,
658 0xcc32, 0x3002,
659 0xcc33, 0x1002,
660 0xcc34, 0x2b82,
661 0xcc35, 0x3012,
662 0xcc36, 0x1002,
663 0xcc37, 0x5663,
664 0xcc38, 0x302,
665 0xcc39, 0x401e,
666 0xcc3a, 0x6f72,
667 0xcc3b, 0x1002,
668 0xcc3c, 0x628f,
669 0xcc3d, 0x2be2,
670 0xcc3e, 0x3012,
671 0xcc3f, 0x1002,
672 0xcc40, 0x22cd,
673 0xcc41, 0x301d,
674 0xcc42, 0x2e52,
675 0xcc43, 0x3012,
676 0xcc44, 0x1002,
677 0xcc45, 0x2522,
678 0xcc46, 0x3012,
679 0xcc47, 0x1002,
680 0xcc48, 0x2da2,
681 0xcc49, 0x3012,
682 0xcc4a, 0x1002,
683 0xcc4b, 0x2ca2,
684 0xcc4c, 0x3012,
685 0xcc4d, 0x1002,
686 0xcc4e, 0x2fa4,
687 0xcc4f, 0x3cd4,
688 0xcc50, 0x6624,
689 0xcc51, 0x410b,
690 0xcc52, 0x56b3,
691 0xcc53, 0x3c4,
692 0xcc54, 0x2fb2,
693 0xcc55, 0x3002,
694 0xcc56, 0x1002,
695 0xcc57, 0x220b,
696 0xcc58, 0x303b,
697 0xcc59, 0x56b3,
698 0xcc5a, 0x3c3,
699 0xcc5b, 0x866b,
700 0xcc5c, 0x400c,
701 0xcc5d, 0x23a2,
702 0xcc5e, 0x3012,
703 0xcc5f, 0x1002,
704 0xcc60, 0x2da2,
705 0xcc61, 0x3012,
706 0xcc62, 0x1002,
707 0xcc63, 0x2ca2,
708 0xcc64, 0x3012,
709 0xcc65, 0x1002,
710 0xcc66, 0x2fb4,
711 0xcc67, 0x3cd4,
712 0xcc68, 0x6624,
713 0xcc69, 0x56b3,
714 0xcc6a, 0x3c3,
715 0xcc6b, 0x866b,
716 0xcc6c, 0x401c,
717 0xcc6d, 0x2205,
718 0xcc6e, 0x3035,
719 0xcc6f, 0x5b53,
720 0xcc70, 0x2c52,
721 0xcc71, 0x3002,
722 0xcc72, 0x13c2,
723 0xcc73, 0x5cc3,
724 0xcc74, 0x317,
725 0xcc75, 0x2522,
726 0xcc76, 0x3012,
727 0xcc77, 0x1002,
728 0xcc78, 0x2da2,
729 0xcc79, 0x3012,
730 0xcc7a, 0x1002,
731 0xcc7b, 0x2b82,
732 0xcc7c, 0x3012,
733 0xcc7d, 0x1002,
734 0xcc7e, 0x5663,
735 0xcc7f, 0x303,
736 0xcc80, 0x401e,
737 0xcc81, 0x004,
738 0xcc82, 0x2c42,
739 0xcc83, 0x3012,
740 0xcc84, 0x1002,
741 0xcc85, 0x6f72,
742 0xcc86, 0x1002,
743 0xcc87, 0x628f,
744 0xcc88, 0x2304,
745 0xcc89, 0x3c84,
746 0xcc8a, 0x6436,
747 0xcc8b, 0xdff4,
748 0xcc8c, 0x6436,
749 0xcc8d, 0x2ff5,
750 0xcc8e, 0x3005,
751 0xcc8f, 0x8656,
752 0xcc90, 0xdfba,
753 0xcc91, 0x56a3,
754 0xcc92, 0xd05a,
755 0xcc93, 0x21c2,
756 0xcc94, 0x3012,
757 0xcc95, 0x1392,
758 0xcc96, 0xd05a,
759 0xcc97, 0x56a3,
760 0xcc98, 0xdfba,
761 0xcc99, 0x383,
762 0xcc9a, 0x6f72,
763 0xcc9b, 0x1002,
764 0xcc9c, 0x28c5,
765 0xcc9d, 0x3005,
766 0xcc9e, 0x4178,
767 0xcc9f, 0x5653,
768 0xcca0, 0x384,
769 0xcca1, 0x22b2,
770 0xcca2, 0x3012,
771 0xcca3, 0x1002,
772 0xcca4, 0x2be5,
773 0xcca5, 0x3005,
774 0xcca6, 0x41e8,
775 0xcca7, 0x5653,
776 0xcca8, 0x382,
777 0xcca9, 0x002,
778 0xccaa, 0x4258,
779 0xccab, 0x2474,
780 0xccac, 0x3c84,
781 0xccad, 0x6437,
782 0xccae, 0xdff4,
783 0xccaf, 0x6437,
784 0xccb0, 0x2ff5,
785 0xccb1, 0x3c05,
786 0xccb2, 0x8757,
787 0xccb3, 0xb888,
788 0xccb4, 0x9787,
789 0xccb5, 0xdff4,
790 0xccb6, 0x6724,
791 0xccb7, 0x866a,
792 0xccb8, 0x6f72,
793 0xccb9, 0x1002,
794 0xccba, 0x2d01,
795 0xccbb, 0x3011,
796 0xccbc, 0x1001,
797 0xccbd, 0xc620,
798 0xccbe, 0x14e5,
799 0xccbf, 0xc621,
800 0xccc0, 0xc53d,
801 0xccc1, 0xc622,
802 0xccc2, 0x3cbe,
803 0xccc3, 0xc623,
804 0xccc4, 0x4452,
805 0xccc5, 0xc624,
806 0xccc6, 0xc5c5,
807 0xccc7, 0xc625,
808 0xccc8, 0xe01e,
809 0xccc9, 0xc627,
810 0xccca, 0x000,
811 0xcccb, 0xc628,
812 0xcccc, 0x000,
813 0xcccd, 0xc62b,
814 0xccce, 0x000,
815 0xcccf, 0xc62c,
816 0xccd0, 0x000,
817 0xccd1, 0x000,
818 0xccd2, 0x2d01,
819 0xccd3, 0x3011,
820 0xccd4, 0x1001,
821 0xccd5, 0xc620,
822 0xccd6, 0x000,
823 0xccd7, 0xc621,
824 0xccd8, 0x000,
825 0xccd9, 0xc622,
826 0xccda, 0x0ce,
827 0xccdb, 0xc623,
828 0xccdc, 0x07f,
829 0xccdd, 0xc624,
830 0xccde, 0x032,
831 0xccdf, 0xc625,
832 0xcce0, 0x000,
833 0xcce1, 0xc627,
834 0xcce2, 0x000,
835 0xcce3, 0xc628,
836 0xcce4, 0x000,
837 0xcce5, 0xc62b,
838 0xcce6, 0x000,
839 0xcce7, 0xc62c,
840 0xcce8, 0x000,
841 0xcce9, 0x000,
842 0xccea, 0x2d01,
843 0xcceb, 0x3011,
844 0xccec, 0x1001,
845 0xcced, 0xc502,
846 0xccee, 0x609f,
847 0xccef, 0xc600,
848 0xccf0, 0x2a6e,
849 0xccf1, 0xc601,
850 0xccf2, 0x2a2c,
851 0xccf3, 0xc60c,
852 0xccf4, 0x5400,
853 0xccf5, 0xc710,
854 0xccf6, 0x700,
855 0xccf7, 0xc718,
856 0xccf8, 0x700,
857 0xccf9, 0xc720,
858 0xccfa, 0x4700,
859 0xccfb, 0xc728,
860 0xccfc, 0x700,
861 0xccfd, 0xc729,
862 0xccfe, 0x1207,
863 0xccff, 0xc801,
864 0xcd00, 0x7f50,
865 0xcd01, 0xc802,
866 0xcd02, 0x7760,
867 0xcd03, 0xc803,
868 0xcd04, 0x7fce,
869 0xcd05, 0xc804,
870 0xcd06, 0x520e,
871 0xcd07, 0xc805,
872 0xcd08, 0x5c11,
873 0xcd09, 0xc806,
874 0xcd0a, 0x3c51,
875 0xcd0b, 0xc807,
876 0xcd0c, 0x4061,
877 0xcd0d, 0xc808,
878 0xcd0e, 0x49c1,
879 0xcd0f, 0xc809,
880 0xcd10, 0x3840,
881 0xcd11, 0xc80a,
882 0xcd12, 0x000,
883 0xcd13, 0xc821,
884 0xcd14, 0x002,
885 0xcd15, 0xc822,
886 0xcd16, 0x046,
887 0xcd17, 0xc844,
888 0xcd18, 0x182f,
889 0xcd19, 0xc013,
890 0xcd1a, 0xf341,
891 0xcd1b, 0xc01a,
892 0xcd1c, 0x446,
893 0xcd1d, 0xc024,
894 0xcd1e, 0x1000,
895 0xcd1f, 0xc025,
896 0xcd20, 0xa00,
897 0xcd21, 0xc026,
898 0xcd22, 0xc0c,
899 0xcd23, 0xc027,
900 0xcd24, 0xc0c,
901 0xcd25, 0xc029,
902 0xcd26, 0x0a0,
903 0xcd27, 0xc030,
904 0xcd28, 0xa00,
905 0xcd29, 0xc03c,
906 0xcd2a, 0x01c,
907 0xcd2b, 0x000,
908 0xcd2c, 0x2b84,
909 0xcd2d, 0x3c74,
910 0xcd2e, 0x6435,
911 0xcd2f, 0xdff4,
912 0xcd30, 0x6435,
913 0xcd31, 0x2806,
914 0xcd32, 0x3006,
915 0xcd33, 0x8565,
916 0xcd34, 0x2b24,
917 0xcd35, 0x3c24,
918 0xcd36, 0x6436,
919 0xcd37, 0x1002,
920 0xcd38, 0x2b24,
921 0xcd39, 0x3c24,
922 0xcd3a, 0x6436,
923 0xcd3b, 0x4045,
924 0xcd3c, 0x8656,
925 0xcd3d, 0x1002,
926 0xcd3e, 0x2807,
927 0xcd3f, 0x31a7,
928 0xcd40, 0x20c4,
929 0xcd41, 0x3c24,
930 0xcd42, 0x6724,
931 0xcd43, 0x1002,
932 0xcd44, 0x2807,
933 0xcd45, 0x3187,
934 0xcd46, 0x20c4,
935 0xcd47, 0x3c24,
936 0xcd48, 0x6724,
937 0xcd49, 0x1002,
938 0xcd4a, 0x2514,
939 0xcd4b, 0x3c64,
940 0xcd4c, 0x6436,
941 0xcd4d, 0xdff4,
942 0xcd4e, 0x6436,
943 0xcd4f, 0x1002,
944 0xcd50, 0x2806,
945 0xcd51, 0x3cb6,
946 0xcd52, 0xc161,
947 0xcd53, 0x6134,
948 0xcd54, 0x6135,
949 0xcd55, 0x5443,
950 0xcd56, 0x303,
951 0xcd57, 0x6524,
952 0xcd58, 0x00b,
953 0xcd59, 0x1002,
954 0xcd5a, 0xd019,
955 0xcd5b, 0x2104,
956 0xcd5c, 0x3c24,
957 0xcd5d, 0x2105,
958 0xcd5e, 0x3805,
959 0xcd5f, 0x6524,
960 0xcd60, 0xdff4,
961 0xcd61, 0x4005,
962 0xcd62, 0x6524,
963 0xcd63, 0x2e8d,
964 0xcd64, 0x303d,
965 0xcd65, 0x5dd3,
966 0xcd66, 0x306,
967 0xcd67, 0x2ff7,
968 0xcd68, 0x38f7,
969 0xcd69, 0x60b7,
970 0xcd6a, 0xdffd,
971 0xcd6b, 0x00a,
972 0xcd6c, 0x1002,
973 0xcd6d, 0
974 };
975 int i, err;
976
977 err = set_phy_regs(phy, regs);
978 if (!err && modtype == phy_modtype_twinax_long)
979 err = set_phy_regs(phy, preemphasis);
980 if (err)
981 return err;
982
983 msleep(50);
984
985 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000986 err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, twinax_edc[i],
987 twinax_edc[i + 1]);
Divy Le Ray1e882022008-10-08 17:40:07 -0700988 if (!err)
989 phy->priv = edc_twinax;
990 return err;
991}
992
Divy Le Ray74451422009-05-29 12:52:44 +0000993static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
Divy Le Ray1e882022008-10-08 17:40:07 -0700994{
995 int v;
996 unsigned int stat;
997
Ben Hutchings0f07c4e2009-04-29 08:07:20 +0000998 v = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, &stat);
Divy Le Ray1e882022008-10-08 17:40:07 -0700999 if (v)
1000 return v;
1001
1002 if (stat & (1 << 8)) /* module absent */
1003 return phy_modtype_none;
1004
Divy Le Ray74451422009-05-29 12:52:44 +00001005 return ael2xxx_get_module_type(phy, delay_ms);
Divy Le Ray1e882022008-10-08 17:40:07 -07001006}
1007
1008static int ael2005_intr_enable(struct cphy *phy)
1009{
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001010 int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x200);
Divy Le Ray1e882022008-10-08 17:40:07 -07001011 return err ? err : t3_phy_lasi_intr_enable(phy);
1012}
1013
1014static int ael2005_intr_disable(struct cphy *phy)
1015{
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001016 int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0x100);
Divy Le Ray1e882022008-10-08 17:40:07 -07001017 return err ? err : t3_phy_lasi_intr_disable(phy);
1018}
1019
1020static int ael2005_intr_clear(struct cphy *phy)
1021{
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001022 int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL, 0xd00);
Divy Le Ray1e882022008-10-08 17:40:07 -07001023 return err ? err : t3_phy_lasi_intr_clear(phy);
1024}
1025
1026static int ael2005_reset(struct cphy *phy, int wait)
1027{
1028 static struct reg_val regs0[] = {
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001029 { MDIO_MMD_PMAPMD, 0xc001, 0, 1 << 5 },
1030 { MDIO_MMD_PMAPMD, 0xc017, 0, 1 << 5 },
1031 { MDIO_MMD_PMAPMD, 0xc013, 0xffff, 0xf341 },
1032 { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
1033 { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8100 },
1034 { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0x8000 },
1035 { MDIO_MMD_PMAPMD, 0xc210, 0xffff, 0 },
Divy Le Ray1e882022008-10-08 17:40:07 -07001036 { 0, 0, 0, 0 }
1037 };
1038 static struct reg_val regs1[] = {
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001039 { MDIO_MMD_PMAPMD, 0xca00, 0xffff, 0x0080 },
1040 { MDIO_MMD_PMAPMD, 0xca12, 0xffff, 0 },
Divy Le Ray1e882022008-10-08 17:40:07 -07001041 { 0, 0, 0, 0 }
1042 };
1043
Hannes Edera243f842009-02-14 11:16:19 +00001044 int err;
1045 unsigned int lasi_ctrl;
Divy Le Ray1e882022008-10-08 17:40:07 -07001046
Ben Hutchings64318332009-05-19 13:22:30 +00001047 err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL,
1048 &lasi_ctrl);
Divy Le Ray1e882022008-10-08 17:40:07 -07001049 if (err)
1050 return err;
1051
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001052 err = t3_phy_reset(phy, MDIO_MMD_PMAPMD, 0);
Divy Le Ray1e882022008-10-08 17:40:07 -07001053 if (err)
1054 return err;
1055
1056 msleep(125);
1057 phy->priv = edc_none;
1058 err = set_phy_regs(phy, regs0);
1059 if (err)
1060 return err;
1061
1062 msleep(50);
1063
Divy Le Ray74451422009-05-29 12:52:44 +00001064 err = ael2005_get_module_type(phy, 0);
Divy Le Ray1e882022008-10-08 17:40:07 -07001065 if (err < 0)
1066 return err;
1067 phy->modtype = err;
1068
1069 if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1070 err = ael2005_setup_twinax_edc(phy, err);
1071 else
1072 err = ael2005_setup_sr_edc(phy);
1073 if (err)
1074 return err;
1075
1076 err = set_phy_regs(phy, regs1);
1077 if (err)
1078 return err;
1079
1080 /* reset wipes out interrupts, reenable them if they were on */
1081 if (lasi_ctrl & 1)
1082 err = ael2005_intr_enable(phy);
1083 return err;
1084}
1085
1086static int ael2005_intr_handler(struct cphy *phy)
1087{
1088 unsigned int stat;
1089 int ret, edc_needed, cause = 0;
1090
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001091 ret = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_STAT, &stat);
Divy Le Ray1e882022008-10-08 17:40:07 -07001092 if (ret)
1093 return ret;
1094
1095 if (stat & AEL2005_MODDET_IRQ) {
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001096 ret = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AEL2005_GPIO_CTRL,
1097 0xd00);
Divy Le Ray1e882022008-10-08 17:40:07 -07001098 if (ret)
1099 return ret;
1100
1101 /* modules have max 300 ms init time after hot plug */
Divy Le Ray74451422009-05-29 12:52:44 +00001102 ret = ael2005_get_module_type(phy, 300);
Divy Le Ray1e882022008-10-08 17:40:07 -07001103 if (ret < 0)
1104 return ret;
1105
1106 phy->modtype = ret;
1107 if (ret == phy_modtype_none)
1108 edc_needed = phy->priv; /* on unplug retain EDC */
1109 else if (ret == phy_modtype_twinax ||
1110 ret == phy_modtype_twinax_long)
1111 edc_needed = edc_twinax;
1112 else
1113 edc_needed = edc_sr;
1114
1115 if (edc_needed != phy->priv) {
1116 ret = ael2005_reset(phy, 0);
1117 return ret ? ret : cphy_cause_module_change;
1118 }
1119 cause = cphy_cause_module_change;
1120 }
1121
1122 ret = t3_phy_lasi_intr_handler(phy);
1123 if (ret < 0)
1124 return ret;
1125
1126 ret |= cause;
1127 return ret ? ret : cphy_cause_link_change;
1128}
1129
1130static struct cphy_ops ael2005_ops = {
1131 .reset = ael2005_reset,
1132 .intr_enable = ael2005_intr_enable,
1133 .intr_disable = ael2005_intr_disable,
1134 .intr_clear = ael2005_intr_clear,
1135 .intr_handler = ael2005_intr_handler,
1136 .get_link_status = get_link_status_r,
1137 .power_down = ael1002_power_down,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001138 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
Divy Le Ray1e882022008-10-08 17:40:07 -07001139};
1140
1141int t3_ael2005_phy_prep(struct cphy *phy, struct adapter *adapter,
1142 int phy_addr, const struct mdio_ops *mdio_ops)
1143{
1144 cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
1145 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1146 SUPPORTED_IRQ, "10GBASE-R");
1147 msleep(125);
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001148 return t3_mdio_change_bits(phy, MDIO_MMD_PMAPMD, AEL_OPT_SETTINGS, 0,
Divy Le Ray1e882022008-10-08 17:40:07 -07001149 1 << 5);
1150}
1151
1152/*
Divy Le Ray74451422009-05-29 12:52:44 +00001153 * Setup EDC and other parameters for operation with an optical module.
1154 */
1155static 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 */
1183static 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 */
1629static 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 */
1650static 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 */
1660static 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 */
1670static 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 */
1685static 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 */
1748static 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
1787static 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
1798int 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/*
Divy Le Ray1e882022008-10-08 17:40:07 -07001809 * Get link status for a 10GBASE-X device.
1810 */
1811static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
1812 int *duplex, int *fc)
1813{
1814 if (link_ok) {
1815 unsigned int stat0, stat1, stat2;
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001816 int err = t3_mdio_read(phy, MDIO_MMD_PMAPMD,
1817 MDIO_PMA_RXDET, &stat0);
Divy Le Ray1e882022008-10-08 17:40:07 -07001818
1819 if (!err)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001820 err = t3_mdio_read(phy, MDIO_MMD_PCS,
1821 MDIO_PCS_10GBX_STAT1, &stat1);
Divy Le Ray1e882022008-10-08 17:40:07 -07001822 if (!err)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001823 err = t3_mdio_read(phy, MDIO_MMD_PHYXS,
1824 MDIO_PHYXS_LNSTAT, &stat2);
Divy Le Ray1e882022008-10-08 17:40:07 -07001825 if (err)
1826 return err;
1827 *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
1828 }
1829 if (speed)
1830 *speed = SPEED_10000;
1831 if (duplex)
1832 *duplex = DUPLEX_FULL;
1833 return 0;
1834}
1835
Divy Le Ray4d22de32007-01-18 22:04:14 -05001836static struct cphy_ops qt2045_ops = {
1837 .reset = ael1006_reset,
Divy Le Ray9b1e3652008-10-08 17:39:31 -07001838 .intr_enable = t3_phy_lasi_intr_enable,
1839 .intr_disable = t3_phy_lasi_intr_disable,
1840 .intr_clear = t3_phy_lasi_intr_clear,
1841 .intr_handler = t3_phy_lasi_intr_handler,
Divy Le Ray1e882022008-10-08 17:40:07 -07001842 .get_link_status = get_link_status_x,
Divy Le Ray4d22de32007-01-18 22:04:14 -05001843 .power_down = ael1006_power_down,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001844 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
Divy Le Ray4d22de32007-01-18 22:04:14 -05001845};
1846
Divy Le Ray78e46892008-10-08 17:38:01 -07001847int t3_qt2045_phy_prep(struct cphy *phy, struct adapter *adapter,
1848 int phy_addr, const struct mdio_ops *mdio_ops)
Divy Le Ray4d22de32007-01-18 22:04:14 -05001849{
1850 unsigned int stat;
1851
Divy Le Ray04497982008-10-08 17:38:29 -07001852 cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops,
1853 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1854 "10GBASE-CX4");
Divy Le Ray4d22de32007-01-18 22:04:14 -05001855
1856 /*
1857 * Some cards where the PHY is supposed to be at address 0 actually
1858 * have it at 1.
1859 */
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001860 if (!phy_addr &&
1861 !t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &stat) &&
Divy Le Ray4d22de32007-01-18 22:04:14 -05001862 stat == 0xffff)
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001863 phy->mdio.prtad = 1;
Divy Le Ray78e46892008-10-08 17:38:01 -07001864 return 0;
Divy Le Ray4d22de32007-01-18 22:04:14 -05001865}
1866
1867static int xaui_direct_reset(struct cphy *phy, int wait)
1868{
1869 return 0;
1870}
1871
1872static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
1873 int *speed, int *duplex, int *fc)
1874{
1875 if (link_ok) {
1876 unsigned int status;
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001877 int prtad = phy->mdio.prtad;
Divy Le Ray4d22de32007-01-18 22:04:14 -05001878
1879 status = t3_read_reg(phy->adapter,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001880 XGM_REG(A_XGM_SERDES_STAT0, prtad)) |
Divy Le Rayc706bfb2007-05-30 10:01:39 -07001881 t3_read_reg(phy->adapter,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001882 XGM_REG(A_XGM_SERDES_STAT1, prtad)) |
Divy Le Rayc706bfb2007-05-30 10:01:39 -07001883 t3_read_reg(phy->adapter,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001884 XGM_REG(A_XGM_SERDES_STAT2, prtad)) |
Divy Le Rayc706bfb2007-05-30 10:01:39 -07001885 t3_read_reg(phy->adapter,
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001886 XGM_REG(A_XGM_SERDES_STAT3, prtad));
Divy Le Ray4d22de32007-01-18 22:04:14 -05001887 *link_ok = !(status & F_LOWSIG0);
1888 }
1889 if (speed)
1890 *speed = SPEED_10000;
1891 if (duplex)
1892 *duplex = DUPLEX_FULL;
1893 return 0;
1894}
1895
1896static int xaui_direct_power_down(struct cphy *phy, int enable)
1897{
1898 return 0;
1899}
1900
1901static struct cphy_ops xaui_direct_ops = {
1902 .reset = xaui_direct_reset,
1903 .intr_enable = ael1002_intr_noop,
1904 .intr_disable = ael1002_intr_noop,
1905 .intr_clear = ael1002_intr_noop,
1906 .intr_handler = ael1002_intr_noop,
1907 .get_link_status = xaui_direct_get_link_status,
1908 .power_down = xaui_direct_power_down,
1909};
1910
Divy Le Ray78e46892008-10-08 17:38:01 -07001911int t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
1912 int phy_addr, const struct mdio_ops *mdio_ops)
Divy Le Ray4d22de32007-01-18 22:04:14 -05001913{
Ben Hutchings0f07c4e2009-04-29 08:07:20 +00001914 cphy_init(phy, adapter, MDIO_PRTAD_NONE, &xaui_direct_ops, mdio_ops,
Divy Le Ray04497982008-10-08 17:38:29 -07001915 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1916 "10GBASE-CX4");
Divy Le Ray78e46892008-10-08 17:38:01 -07001917 return 0;
Divy Le Ray4d22de32007-01-18 22:04:14 -05001918}