xref: /freebsd/sys/dev/cxgb/common/cxgb_ael1002.c (revision dcc3a33188bceb5b6e819efdb9c5f72d059084b6)
1 /**************************************************************************
2 
3 Copyright (c) 2007-2009, Chelsio Inc.
4 All rights reserved.
5 
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 
9  1. Redistributions of source code must retain the above copyright notice,
10     this list of conditions and the following disclaimer.
11 
12  2. Neither the name of the Chelsio Corporation nor the names of its
13     contributors may be used to endorse or promote products derived from
14     this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 POSSIBILITY OF SUCH DAMAGE.
27 
28 ***************************************************************************/
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include <cxgb_include.h>
34 
35 #undef msleep
36 #define msleep t3_os_sleep
37 
38 enum {
39 	PMD_RSD     = 10,   /* PMA/PMD receive signal detect register */
40 	PCS_STAT1_X = 24,   /* 10GBASE-X PCS status 1 register */
41 	PCS_STAT1_R = 32,   /* 10GBASE-R PCS status 1 register */
42 	XS_LN_STAT  = 24    /* XS lane status register */
43 };
44 
45 enum {
46 	AEL100X_TX_DISABLE  = 9,
47 	AEL100X_TX_CONFIG1  = 0xc002,
48 	AEL1002_PWR_DOWN_HI = 0xc011,
49 	AEL1002_PWR_DOWN_LO = 0xc012,
50 	AEL1002_XFI_EQL     = 0xc015,
51 	AEL1002_LB_EN       = 0xc017,
52 	AEL_OPT_SETTINGS    = 0xc017,
53 	AEL_I2C_CTRL        = 0xc30a,
54 	AEL_I2C_DATA        = 0xc30b,
55 	AEL_I2C_STAT        = 0xc30c,
56 	AEL2005_GPIO_CTRL   = 0xc214,
57 	AEL2005_GPIO_STAT   = 0xc215,
58 };
59 
60 enum { edc_none, edc_sr, edc_twinax };
61 
62 /* PHY module I2C device address */
63 enum {
64 	MODULE_DEV_ADDR	= 0xa0,
65 	SFF_DEV_ADDR	= 0xa2,
66 };
67 
68 /* PHY transceiver type */
69 enum {
70 	phy_transtype_unknown = 0,
71 	phy_transtype_sfp     = 3,
72 	phy_transtype_xfp     = 6,
73 };
74 
75 #define AEL2005_MODDET_IRQ 4
76 
77 struct reg_val {
78 	unsigned short mmd_addr;
79 	unsigned short reg_addr;
80 	unsigned short clear_bits;
81 	unsigned short set_bits;
82 };
83 
84 static int get_module_type(struct cphy *phy);
85 
86 static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
87 {
88 	int err;
89 
90 	for (err = 0; rv->mmd_addr && !err; rv++) {
91 		if (rv->clear_bits == 0xffff)
92 			err = mdio_write(phy, rv->mmd_addr, rv->reg_addr,
93 					 rv->set_bits);
94 		else
95 			err = t3_mdio_change_bits(phy, rv->mmd_addr,
96 						  rv->reg_addr, rv->clear_bits,
97 						  rv->set_bits);
98 	}
99 	return err;
100 }
101 
102 static void ael100x_txon(struct cphy *phy)
103 {
104 	int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
105 
106 	msleep(100);
107 	t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
108 	msleep(30);
109 }
110 
111 static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
112 {
113 	int i, err;
114 	unsigned int stat, data;
115 
116 	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
117 			 (dev_addr << 8) | (1 << 8) | word_addr);
118 	if (err)
119 		return err;
120 
121 	for (i = 0; i < 200; i++) {
122 		msleep(1);
123 		err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
124 		if (err)
125 			return err;
126 		if ((stat & 3) == 1) {
127 			err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA,
128 					&data);
129 			if (err)
130 				return err;
131 			return data >> 8;
132 		}
133 	}
134 	CH_WARN(phy->adapter, "PHY %u I2C read of addr %u timed out\n",
135 		phy->addr, word_addr);
136 	return -ETIMEDOUT;
137 }
138 
139 static int ael_i2c_wr(struct cphy *phy, int dev_addr, int word_addr, int data)
140 {
141 	int i, err;
142 	unsigned int stat;
143 
144 	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, data);
145 	if (err)
146 		return err;
147 
148 	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
149 			 (dev_addr << 8) | word_addr);
150 	if (err)
151 		return err;
152 
153 	for (i = 0; i < 200; i++) {
154 		msleep(1);
155 		err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
156 		if (err)
157 			return err;
158 		if ((stat & 3) == 1)
159 			return 0;
160 	}
161 	CH_WARN(phy->adapter, "PHY %u I2C Write of addr %u timed out\n",
162 		phy->addr, word_addr);
163 	return -ETIMEDOUT;
164 }
165 
166 static int get_phytrans_type(struct cphy *phy)
167 {
168 	int v;
169 
170 	v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0);
171 	if (v < 0)
172 		return phy_transtype_unknown;
173 
174 	return v;
175 }
176 
177 static int ael_laser_down(struct cphy *phy, int enable)
178 {
179 	int v, dev_addr;
180 
181 	v = get_phytrans_type(phy);
182 	if (v < 0)
183 		return v;
184 
185 	if (v == phy_transtype_sfp) {
186 		/* Check SFF Soft TX disable is supported */
187 		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 93);
188 		if (v < 0)
189 			return v;
190 
191 		v &= 0x40;
192 		if (!v)
193 			return v;
194 
195 		dev_addr = SFF_DEV_ADDR;
196 	} else if (v == phy_transtype_xfp)
197 		dev_addr = MODULE_DEV_ADDR;
198 	else
199 		return v;
200 
201 	v = ael_i2c_rd(phy, dev_addr, 110);
202 	if (v < 0)
203 		return v;
204 
205 	if (enable)
206 		v |= 0x40;
207 	else
208 		v &= ~0x40;
209 
210 	v = ael_i2c_wr(phy, dev_addr, 110, v);
211 
212 	return v;
213 }
214 
215 static int ael1002_power_down(struct cphy *phy, int enable)
216 {
217 	int err;
218 
219 	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable);
220 	if (!err)
221 		err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
222 					  BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
223 	return err;
224 }
225 
226 static int ael1002_get_module_type(struct cphy *phy, int delay_ms)
227 {
228 	int v;
229 
230 	if (delay_ms)
231 		msleep(delay_ms);
232 
233 	v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0);
234 
235 	return v == -ETIMEDOUT ? phy_modtype_none : get_module_type(phy);
236 }
237 
238 static int ael1002_reset(struct cphy *phy, int wait)
239 {
240 	int err;
241 
242 	if ((err = ael1002_power_down(phy, 0)) ||
243 	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) ||
244 	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) ||
245 	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) ||
246 	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) ||
247 	    (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
248 				       0, 1 << 5)))
249 		return err;
250 
251 	err = ael1002_get_module_type(phy, 300);
252 	if (err >= 0)
253 		phy->modtype = err;
254 
255 	return 0;
256 }
257 
258 static int ael1002_intr_noop(struct cphy *phy)
259 {
260 	return 0;
261 }
262 
263 /*
264  * Get link status for a 10GBASE-R device.
265  */
266 static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed,
267 			     int *duplex, int *fc)
268 {
269 	if (link_ok) {
270 		unsigned int stat0, stat1, stat2;
271 		int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
272 
273 		if (!err)
274 			err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1);
275 		if (!err)
276 			err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
277 		if (err)
278 			return err;
279 		*link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
280 	}
281 	if (speed)
282 		*speed = SPEED_10000;
283 	if (duplex)
284 		*duplex = DUPLEX_FULL;
285 	return 0;
286 }
287 
288 #ifdef C99_NOT_SUPPORTED
289 static struct cphy_ops ael1002_ops = {
290 	ael1002_reset,
291 	ael1002_intr_noop,
292 	ael1002_intr_noop,
293 	ael1002_intr_noop,
294 	ael1002_intr_noop,
295 	NULL,
296 	NULL,
297 	NULL,
298 	NULL,
299 	NULL,
300 	get_link_status_r,
301 	ael1002_power_down,
302 };
303 #else
304 static struct cphy_ops ael1002_ops = {
305 	.reset           = ael1002_reset,
306 	.intr_enable     = ael1002_intr_noop,
307 	.intr_disable    = ael1002_intr_noop,
308 	.intr_clear      = ael1002_intr_noop,
309 	.intr_handler    = ael1002_intr_noop,
310 	.get_link_status = get_link_status_r,
311 	.power_down      = ael1002_power_down,
312 };
313 #endif
314 
315 int t3_ael1002_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
316 			const struct mdio_ops *mdio_ops)
317 {
318 	int err;
319 
320 	cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops,
321 		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
322 		  "10GBASE-R");
323 	ael100x_txon(phy);
324 	ael_laser_down(phy, 0);
325 
326 	err = ael1002_get_module_type(phy, 0);
327 	if (err >= 0)
328 		phy->modtype = err;
329 
330 	return 0;
331 }
332 
333 static int ael1006_reset(struct cphy *phy, int wait)
334 {
335 	int err;
336 
337 	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
338 	if (err)
339 		return err;
340 
341 	t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
342 			 F_GPIO6_OUT_VAL, 0);
343 
344 	msleep(125);
345 
346 	t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
347 			 F_GPIO6_OUT_VAL, F_GPIO6_OUT_VAL);
348 
349 	msleep(125);
350 
351 	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
352 	if (err)
353 		return err;
354 
355 	msleep(125);
356 
357 	err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 1);
358 	if (err)
359 		return err;
360 
361 	msleep(125);
362 
363 	err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 0);
364 
365 	return err;
366 
367 }
368 
369 static int ael1006_power_down(struct cphy *phy, int enable)
370 {
371 	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
372 				   BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
373 }
374 
375 #ifdef C99_NOT_SUPPORTED
376 static struct cphy_ops ael1006_ops = {
377 	ael1006_reset,
378 	t3_phy_lasi_intr_enable,
379 	t3_phy_lasi_intr_disable,
380 	t3_phy_lasi_intr_clear,
381 	t3_phy_lasi_intr_handler,
382 	NULL,
383 	NULL,
384 	NULL,
385 	NULL,
386 	NULL,
387 	get_link_status_r,
388 	ael1006_power_down,
389 };
390 #else
391 static struct cphy_ops ael1006_ops = {
392 	.reset           = ael1006_reset,
393 	.intr_enable     = t3_phy_lasi_intr_enable,
394 	.intr_disable    = t3_phy_lasi_intr_disable,
395 	.intr_clear      = t3_phy_lasi_intr_clear,
396 	.intr_handler    = t3_phy_lasi_intr_handler,
397 	.get_link_status = get_link_status_r,
398 	.power_down      = ael1006_power_down,
399 };
400 #endif
401 
402 int t3_ael1006_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
403 			const struct mdio_ops *mdio_ops)
404 {
405 	cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops,
406 		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
407 		  "10GBASE-SR");
408 	ael100x_txon(phy);
409 	return 0;
410 }
411 
412 static int ael2005_setup_sr_edc(struct cphy *phy)
413 {
414 	static struct reg_val regs[] = {
415 		{ MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 },
416 		{ MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a },
417 		{ MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 },
418 		{ 0, 0, 0, 0 }
419 	};
420 	static u16 sr_edc[] = {
421 		0xcc00, 0x2ff4,
422 		0xcc01, 0x3cd4,
423 		0xcc02, 0x2015,
424 		0xcc03, 0x3105,
425 		0xcc04, 0x6524,
426 		0xcc05, 0x27ff,
427 		0xcc06, 0x300f,
428 		0xcc07, 0x2c8b,
429 		0xcc08, 0x300b,
430 		0xcc09, 0x4009,
431 		0xcc0a, 0x400e,
432 		0xcc0b, 0x2f72,
433 		0xcc0c, 0x3002,
434 		0xcc0d, 0x1002,
435 		0xcc0e, 0x2172,
436 		0xcc0f, 0x3012,
437 		0xcc10, 0x1002,
438 		0xcc11, 0x25d2,
439 		0xcc12, 0x3012,
440 		0xcc13, 0x1002,
441 		0xcc14, 0xd01e,
442 		0xcc15, 0x27d2,
443 		0xcc16, 0x3012,
444 		0xcc17, 0x1002,
445 		0xcc18, 0x2004,
446 		0xcc19, 0x3c84,
447 		0xcc1a, 0x6436,
448 		0xcc1b, 0x2007,
449 		0xcc1c, 0x3f87,
450 		0xcc1d, 0x8676,
451 		0xcc1e, 0x40b7,
452 		0xcc1f, 0xa746,
453 		0xcc20, 0x4047,
454 		0xcc21, 0x5673,
455 		0xcc22, 0x2982,
456 		0xcc23, 0x3002,
457 		0xcc24, 0x13d2,
458 		0xcc25, 0x8bbd,
459 		0xcc26, 0x2862,
460 		0xcc27, 0x3012,
461 		0xcc28, 0x1002,
462 		0xcc29, 0x2092,
463 		0xcc2a, 0x3012,
464 		0xcc2b, 0x1002,
465 		0xcc2c, 0x5cc3,
466 		0xcc2d, 0x314,
467 		0xcc2e, 0x2942,
468 		0xcc2f, 0x3002,
469 		0xcc30, 0x1002,
470 		0xcc31, 0xd019,
471 		0xcc32, 0x2032,
472 		0xcc33, 0x3012,
473 		0xcc34, 0x1002,
474 		0xcc35, 0x2a04,
475 		0xcc36, 0x3c74,
476 		0xcc37, 0x6435,
477 		0xcc38, 0x2fa4,
478 		0xcc39, 0x3cd4,
479 		0xcc3a, 0x6624,
480 		0xcc3b, 0x5563,
481 		0xcc3c, 0x2d42,
482 		0xcc3d, 0x3002,
483 		0xcc3e, 0x13d2,
484 		0xcc3f, 0x464d,
485 		0xcc40, 0x2862,
486 		0xcc41, 0x3012,
487 		0xcc42, 0x1002,
488 		0xcc43, 0x2032,
489 		0xcc44, 0x3012,
490 		0xcc45, 0x1002,
491 		0xcc46, 0x2fb4,
492 		0xcc47, 0x3cd4,
493 		0xcc48, 0x6624,
494 		0xcc49, 0x5563,
495 		0xcc4a, 0x2d42,
496 		0xcc4b, 0x3002,
497 		0xcc4c, 0x13d2,
498 		0xcc4d, 0x2ed2,
499 		0xcc4e, 0x3002,
500 		0xcc4f, 0x1002,
501 		0xcc50, 0x2fd2,
502 		0xcc51, 0x3002,
503 		0xcc52, 0x1002,
504 		0xcc53, 0x004,
505 		0xcc54, 0x2942,
506 		0xcc55, 0x3002,
507 		0xcc56, 0x1002,
508 		0xcc57, 0x2092,
509 		0xcc58, 0x3012,
510 		0xcc59, 0x1002,
511 		0xcc5a, 0x5cc3,
512 		0xcc5b, 0x317,
513 		0xcc5c, 0x2f72,
514 		0xcc5d, 0x3002,
515 		0xcc5e, 0x1002,
516 		0xcc5f, 0x2942,
517 		0xcc60, 0x3002,
518 		0xcc61, 0x1002,
519 		0xcc62, 0x22cd,
520 		0xcc63, 0x301d,
521 		0xcc64, 0x2862,
522 		0xcc65, 0x3012,
523 		0xcc66, 0x1002,
524 		0xcc67, 0x2ed2,
525 		0xcc68, 0x3002,
526 		0xcc69, 0x1002,
527 		0xcc6a, 0x2d72,
528 		0xcc6b, 0x3002,
529 		0xcc6c, 0x1002,
530 		0xcc6d, 0x628f,
531 		0xcc6e, 0x2112,
532 		0xcc6f, 0x3012,
533 		0xcc70, 0x1002,
534 		0xcc71, 0x5aa3,
535 		0xcc72, 0x2dc2,
536 		0xcc73, 0x3002,
537 		0xcc74, 0x1312,
538 		0xcc75, 0x6f72,
539 		0xcc76, 0x1002,
540 		0xcc77, 0x2807,
541 		0xcc78, 0x31a7,
542 		0xcc79, 0x20c4,
543 		0xcc7a, 0x3c24,
544 		0xcc7b, 0x6724,
545 		0xcc7c, 0x1002,
546 		0xcc7d, 0x2807,
547 		0xcc7e, 0x3187,
548 		0xcc7f, 0x20c4,
549 		0xcc80, 0x3c24,
550 		0xcc81, 0x6724,
551 		0xcc82, 0x1002,
552 		0xcc83, 0x2514,
553 		0xcc84, 0x3c64,
554 		0xcc85, 0x6436,
555 		0xcc86, 0xdff4,
556 		0xcc87, 0x6436,
557 		0xcc88, 0x1002,
558 		0xcc89, 0x40a4,
559 		0xcc8a, 0x643c,
560 		0xcc8b, 0x4016,
561 		0xcc8c, 0x8c6c,
562 		0xcc8d, 0x2b24,
563 		0xcc8e, 0x3c24,
564 		0xcc8f, 0x6435,
565 		0xcc90, 0x1002,
566 		0xcc91, 0x2b24,
567 		0xcc92, 0x3c24,
568 		0xcc93, 0x643a,
569 		0xcc94, 0x4025,
570 		0xcc95, 0x8a5a,
571 		0xcc96, 0x1002,
572 		0xcc97, 0x2731,
573 		0xcc98, 0x3011,
574 		0xcc99, 0x1001,
575 		0xcc9a, 0xc7a0,
576 		0xcc9b, 0x100,
577 		0xcc9c, 0xc502,
578 		0xcc9d, 0x53ac,
579 		0xcc9e, 0xc503,
580 		0xcc9f, 0xd5d5,
581 		0xcca0, 0xc600,
582 		0xcca1, 0x2a6d,
583 		0xcca2, 0xc601,
584 		0xcca3, 0x2a4c,
585 		0xcca4, 0xc602,
586 		0xcca5, 0x111,
587 		0xcca6, 0xc60c,
588 		0xcca7, 0x5900,
589 		0xcca8, 0xc710,
590 		0xcca9, 0x700,
591 		0xccaa, 0xc718,
592 		0xccab, 0x700,
593 		0xccac, 0xc720,
594 		0xccad, 0x4700,
595 		0xccae, 0xc801,
596 		0xccaf, 0x7f50,
597 		0xccb0, 0xc802,
598 		0xccb1, 0x7760,
599 		0xccb2, 0xc803,
600 		0xccb3, 0x7fce,
601 		0xccb4, 0xc804,
602 		0xccb5, 0x5700,
603 		0xccb6, 0xc805,
604 		0xccb7, 0x5f11,
605 		0xccb8, 0xc806,
606 		0xccb9, 0x4751,
607 		0xccba, 0xc807,
608 		0xccbb, 0x57e1,
609 		0xccbc, 0xc808,
610 		0xccbd, 0x2700,
611 		0xccbe, 0xc809,
612 		0xccbf, 0x000,
613 		0xccc0, 0xc821,
614 		0xccc1, 0x002,
615 		0xccc2, 0xc822,
616 		0xccc3, 0x014,
617 		0xccc4, 0xc832,
618 		0xccc5, 0x1186,
619 		0xccc6, 0xc847,
620 		0xccc7, 0x1e02,
621 		0xccc8, 0xc013,
622 		0xccc9, 0xf341,
623 		0xccca, 0xc01a,
624 		0xcccb, 0x446,
625 		0xcccc, 0xc024,
626 		0xcccd, 0x1000,
627 		0xccce, 0xc025,
628 		0xcccf, 0xa00,
629 		0xccd0, 0xc026,
630 		0xccd1, 0xc0c,
631 		0xccd2, 0xc027,
632 		0xccd3, 0xc0c,
633 		0xccd4, 0xc029,
634 		0xccd5, 0x0a0,
635 		0xccd6, 0xc030,
636 		0xccd7, 0xa00,
637 		0xccd8, 0xc03c,
638 		0xccd9, 0x01c,
639 		0xccda, 0xc005,
640 		0xccdb, 0x7a06,
641 		0xccdc, 0x000,
642 		0xccdd, 0x2731,
643 		0xccde, 0x3011,
644 		0xccdf, 0x1001,
645 		0xcce0, 0xc620,
646 		0xcce1, 0x000,
647 		0xcce2, 0xc621,
648 		0xcce3, 0x03f,
649 		0xcce4, 0xc622,
650 		0xcce5, 0x000,
651 		0xcce6, 0xc623,
652 		0xcce7, 0x000,
653 		0xcce8, 0xc624,
654 		0xcce9, 0x000,
655 		0xccea, 0xc625,
656 		0xcceb, 0x000,
657 		0xccec, 0xc627,
658 		0xcced, 0x000,
659 		0xccee, 0xc628,
660 		0xccef, 0x000,
661 		0xccf0, 0xc62c,
662 		0xccf1, 0x000,
663 		0xccf2, 0x000,
664 		0xccf3, 0x2806,
665 		0xccf4, 0x3cb6,
666 		0xccf5, 0xc161,
667 		0xccf6, 0x6134,
668 		0xccf7, 0x6135,
669 		0xccf8, 0x5443,
670 		0xccf9, 0x303,
671 		0xccfa, 0x6524,
672 		0xccfb, 0x00b,
673 		0xccfc, 0x1002,
674 		0xccfd, 0x2104,
675 		0xccfe, 0x3c24,
676 		0xccff, 0x2105,
677 		0xcd00, 0x3805,
678 		0xcd01, 0x6524,
679 		0xcd02, 0xdff4,
680 		0xcd03, 0x4005,
681 		0xcd04, 0x6524,
682 		0xcd05, 0x1002,
683 		0xcd06, 0x5dd3,
684 		0xcd07, 0x306,
685 		0xcd08, 0x2ff7,
686 		0xcd09, 0x38f7,
687 		0xcd0a, 0x60b7,
688 		0xcd0b, 0xdffd,
689 		0xcd0c, 0x00a,
690 		0xcd0d, 0x1002,
691 		0xcd0e, 0
692 	};
693 	int i, err;
694 
695 	err = set_phy_regs(phy, regs);
696 	if (err)
697 		return err;
698 
699 	msleep(50);
700 
701 	for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
702 		err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i],
703 				 sr_edc[i + 1]);
704 	if (!err)
705 		phy->priv = edc_sr;
706 	return err;
707 }
708 
709 static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
710 {
711 	static struct reg_val regs[] = {
712 		{ MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 },
713 		{ 0, 0, 0, 0 }
714 	};
715 	static struct reg_val preemphasis[] = {
716 		{ MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 },
717 		{ MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 },
718 		{ 0, 0, 0, 0 }
719 	};
720 	static u16 twinax_edc[] = {
721 		0xcc00, 0x4009,
722 		0xcc01, 0x27ff,
723 		0xcc02, 0x300f,
724 		0xcc03, 0x40aa,
725 		0xcc04, 0x401c,
726 		0xcc05, 0x401e,
727 		0xcc06, 0x2ff4,
728 		0xcc07, 0x3cd4,
729 		0xcc08, 0x2035,
730 		0xcc09, 0x3145,
731 		0xcc0a, 0x6524,
732 		0xcc0b, 0x26a2,
733 		0xcc0c, 0x3012,
734 		0xcc0d, 0x1002,
735 		0xcc0e, 0x29c2,
736 		0xcc0f, 0x3002,
737 		0xcc10, 0x1002,
738 		0xcc11, 0x2072,
739 		0xcc12, 0x3012,
740 		0xcc13, 0x1002,
741 		0xcc14, 0x22cd,
742 		0xcc15, 0x301d,
743 		0xcc16, 0x2e52,
744 		0xcc17, 0x3012,
745 		0xcc18, 0x1002,
746 		0xcc19, 0x28e2,
747 		0xcc1a, 0x3002,
748 		0xcc1b, 0x1002,
749 		0xcc1c, 0x628f,
750 		0xcc1d, 0x2ac2,
751 		0xcc1e, 0x3012,
752 		0xcc1f, 0x1002,
753 		0xcc20, 0x5553,
754 		0xcc21, 0x2ae2,
755 		0xcc22, 0x3002,
756 		0xcc23, 0x1302,
757 		0xcc24, 0x401e,
758 		0xcc25, 0x2be2,
759 		0xcc26, 0x3012,
760 		0xcc27, 0x1002,
761 		0xcc28, 0x2da2,
762 		0xcc29, 0x3012,
763 		0xcc2a, 0x1002,
764 		0xcc2b, 0x2ba2,
765 		0xcc2c, 0x3002,
766 		0xcc2d, 0x1002,
767 		0xcc2e, 0x5ee3,
768 		0xcc2f, 0x305,
769 		0xcc30, 0x400e,
770 		0xcc31, 0x2bc2,
771 		0xcc32, 0x3002,
772 		0xcc33, 0x1002,
773 		0xcc34, 0x2b82,
774 		0xcc35, 0x3012,
775 		0xcc36, 0x1002,
776 		0xcc37, 0x5663,
777 		0xcc38, 0x302,
778 		0xcc39, 0x401e,
779 		0xcc3a, 0x6f72,
780 		0xcc3b, 0x1002,
781 		0xcc3c, 0x628f,
782 		0xcc3d, 0x2be2,
783 		0xcc3e, 0x3012,
784 		0xcc3f, 0x1002,
785 		0xcc40, 0x22cd,
786 		0xcc41, 0x301d,
787 		0xcc42, 0x2e52,
788 		0xcc43, 0x3012,
789 		0xcc44, 0x1002,
790 		0xcc45, 0x2522,
791 		0xcc46, 0x3012,
792 		0xcc47, 0x1002,
793 		0xcc48, 0x2da2,
794 		0xcc49, 0x3012,
795 		0xcc4a, 0x1002,
796 		0xcc4b, 0x2ca2,
797 		0xcc4c, 0x3012,
798 		0xcc4d, 0x1002,
799 		0xcc4e, 0x2fa4,
800 		0xcc4f, 0x3cd4,
801 		0xcc50, 0x6624,
802 		0xcc51, 0x410b,
803 		0xcc52, 0x56b3,
804 		0xcc53, 0x3c4,
805 		0xcc54, 0x2fb2,
806 		0xcc55, 0x3002,
807 		0xcc56, 0x1002,
808 		0xcc57, 0x220b,
809 		0xcc58, 0x303b,
810 		0xcc59, 0x56b3,
811 		0xcc5a, 0x3c3,
812 		0xcc5b, 0x866b,
813 		0xcc5c, 0x400c,
814 		0xcc5d, 0x23a2,
815 		0xcc5e, 0x3012,
816 		0xcc5f, 0x1002,
817 		0xcc60, 0x2da2,
818 		0xcc61, 0x3012,
819 		0xcc62, 0x1002,
820 		0xcc63, 0x2ca2,
821 		0xcc64, 0x3012,
822 		0xcc65, 0x1002,
823 		0xcc66, 0x2fb4,
824 		0xcc67, 0x3cd4,
825 		0xcc68, 0x6624,
826 		0xcc69, 0x56b3,
827 		0xcc6a, 0x3c3,
828 		0xcc6b, 0x866b,
829 		0xcc6c, 0x401c,
830 		0xcc6d, 0x2205,
831 		0xcc6e, 0x3035,
832 		0xcc6f, 0x5b53,
833 		0xcc70, 0x2c52,
834 		0xcc71, 0x3002,
835 		0xcc72, 0x13c2,
836 		0xcc73, 0x5cc3,
837 		0xcc74, 0x317,
838 		0xcc75, 0x2522,
839 		0xcc76, 0x3012,
840 		0xcc77, 0x1002,
841 		0xcc78, 0x2da2,
842 		0xcc79, 0x3012,
843 		0xcc7a, 0x1002,
844 		0xcc7b, 0x2b82,
845 		0xcc7c, 0x3012,
846 		0xcc7d, 0x1002,
847 		0xcc7e, 0x5663,
848 		0xcc7f, 0x303,
849 		0xcc80, 0x401e,
850 		0xcc81, 0x004,
851 		0xcc82, 0x2c42,
852 		0xcc83, 0x3012,
853 		0xcc84, 0x1002,
854 		0xcc85, 0x6f72,
855 		0xcc86, 0x1002,
856 		0xcc87, 0x628f,
857 		0xcc88, 0x2304,
858 		0xcc89, 0x3c84,
859 		0xcc8a, 0x6436,
860 		0xcc8b, 0xdff4,
861 		0xcc8c, 0x6436,
862 		0xcc8d, 0x2ff5,
863 		0xcc8e, 0x3005,
864 		0xcc8f, 0x8656,
865 		0xcc90, 0xdfba,
866 		0xcc91, 0x56a3,
867 		0xcc92, 0xd05a,
868 		0xcc93, 0x21c2,
869 		0xcc94, 0x3012,
870 		0xcc95, 0x1392,
871 		0xcc96, 0xd05a,
872 		0xcc97, 0x56a3,
873 		0xcc98, 0xdfba,
874 		0xcc99, 0x383,
875 		0xcc9a, 0x6f72,
876 		0xcc9b, 0x1002,
877 		0xcc9c, 0x28c5,
878 		0xcc9d, 0x3005,
879 		0xcc9e, 0x4178,
880 		0xcc9f, 0x5653,
881 		0xcca0, 0x384,
882 		0xcca1, 0x22b2,
883 		0xcca2, 0x3012,
884 		0xcca3, 0x1002,
885 		0xcca4, 0x2be5,
886 		0xcca5, 0x3005,
887 		0xcca6, 0x41e8,
888 		0xcca7, 0x5653,
889 		0xcca8, 0x382,
890 		0xcca9, 0x002,
891 		0xccaa, 0x4258,
892 		0xccab, 0x2474,
893 		0xccac, 0x3c84,
894 		0xccad, 0x6437,
895 		0xccae, 0xdff4,
896 		0xccaf, 0x6437,
897 		0xccb0, 0x2ff5,
898 		0xccb1, 0x3c05,
899 		0xccb2, 0x8757,
900 		0xccb3, 0xb888,
901 		0xccb4, 0x9787,
902 		0xccb5, 0xdff4,
903 		0xccb6, 0x6724,
904 		0xccb7, 0x866a,
905 		0xccb8, 0x6f72,
906 		0xccb9, 0x1002,
907 		0xccba, 0x2d01,
908 		0xccbb, 0x3011,
909 		0xccbc, 0x1001,
910 		0xccbd, 0xc620,
911 		0xccbe, 0x14e5,
912 		0xccbf, 0xc621,
913 		0xccc0, 0xc53d,
914 		0xccc1, 0xc622,
915 		0xccc2, 0x3cbe,
916 		0xccc3, 0xc623,
917 		0xccc4, 0x4452,
918 		0xccc5, 0xc624,
919 		0xccc6, 0xc5c5,
920 		0xccc7, 0xc625,
921 		0xccc8, 0xe01e,
922 		0xccc9, 0xc627,
923 		0xccca, 0x000,
924 		0xcccb, 0xc628,
925 		0xcccc, 0x000,
926 		0xcccd, 0xc62b,
927 		0xccce, 0x000,
928 		0xcccf, 0xc62c,
929 		0xccd0, 0x000,
930 		0xccd1, 0x000,
931 		0xccd2, 0x2d01,
932 		0xccd3, 0x3011,
933 		0xccd4, 0x1001,
934 		0xccd5, 0xc620,
935 		0xccd6, 0x000,
936 		0xccd7, 0xc621,
937 		0xccd8, 0x000,
938 		0xccd9, 0xc622,
939 		0xccda, 0x0ce,
940 		0xccdb, 0xc623,
941 		0xccdc, 0x07f,
942 		0xccdd, 0xc624,
943 		0xccde, 0x032,
944 		0xccdf, 0xc625,
945 		0xcce0, 0x000,
946 		0xcce1, 0xc627,
947 		0xcce2, 0x000,
948 		0xcce3, 0xc628,
949 		0xcce4, 0x000,
950 		0xcce5, 0xc62b,
951 		0xcce6, 0x000,
952 		0xcce7, 0xc62c,
953 		0xcce8, 0x000,
954 		0xcce9, 0x000,
955 		0xccea, 0x2d01,
956 		0xcceb, 0x3011,
957 		0xccec, 0x1001,
958 		0xcced, 0xc502,
959 		0xccee, 0x609f,
960 		0xccef, 0xc600,
961 		0xccf0, 0x2a6e,
962 		0xccf1, 0xc601,
963 		0xccf2, 0x2a2c,
964 		0xccf3, 0xc60c,
965 		0xccf4, 0x5400,
966 		0xccf5, 0xc710,
967 		0xccf6, 0x700,
968 		0xccf7, 0xc718,
969 		0xccf8, 0x700,
970 		0xccf9, 0xc720,
971 		0xccfa, 0x4700,
972 		0xccfb, 0xc728,
973 		0xccfc, 0x700,
974 		0xccfd, 0xc729,
975 		0xccfe, 0x1207,
976 		0xccff, 0xc801,
977 		0xcd00, 0x7f50,
978 		0xcd01, 0xc802,
979 		0xcd02, 0x7760,
980 		0xcd03, 0xc803,
981 		0xcd04, 0x7fce,
982 		0xcd05, 0xc804,
983 		0xcd06, 0x520e,
984 		0xcd07, 0xc805,
985 		0xcd08, 0x5c11,
986 		0xcd09, 0xc806,
987 		0xcd0a, 0x3c51,
988 		0xcd0b, 0xc807,
989 		0xcd0c, 0x4061,
990 		0xcd0d, 0xc808,
991 		0xcd0e, 0x49c1,
992 		0xcd0f, 0xc809,
993 		0xcd10, 0x3840,
994 		0xcd11, 0xc80a,
995 		0xcd12, 0x000,
996 		0xcd13, 0xc821,
997 		0xcd14, 0x002,
998 		0xcd15, 0xc822,
999 		0xcd16, 0x046,
1000 		0xcd17, 0xc844,
1001 		0xcd18, 0x182f,
1002 		0xcd19, 0xc013,
1003 		0xcd1a, 0xf341,
1004 		0xcd1b, 0xc01a,
1005 		0xcd1c, 0x446,
1006 		0xcd1d, 0xc024,
1007 		0xcd1e, 0x1000,
1008 		0xcd1f, 0xc025,
1009 		0xcd20, 0xa00,
1010 		0xcd21, 0xc026,
1011 		0xcd22, 0xc0c,
1012 		0xcd23, 0xc027,
1013 		0xcd24, 0xc0c,
1014 		0xcd25, 0xc029,
1015 		0xcd26, 0x0a0,
1016 		0xcd27, 0xc030,
1017 		0xcd28, 0xa00,
1018 		0xcd29, 0xc03c,
1019 		0xcd2a, 0x01c,
1020 		0xcd2b, 0x000,
1021 		0xcd2c, 0x2b84,
1022 		0xcd2d, 0x3c74,
1023 		0xcd2e, 0x6435,
1024 		0xcd2f, 0xdff4,
1025 		0xcd30, 0x6435,
1026 		0xcd31, 0x2806,
1027 		0xcd32, 0x3006,
1028 		0xcd33, 0x8565,
1029 		0xcd34, 0x2b24,
1030 		0xcd35, 0x3c24,
1031 		0xcd36, 0x6436,
1032 		0xcd37, 0x1002,
1033 		0xcd38, 0x2b24,
1034 		0xcd39, 0x3c24,
1035 		0xcd3a, 0x6436,
1036 		0xcd3b, 0x4045,
1037 		0xcd3c, 0x8656,
1038 		0xcd3d, 0x1002,
1039 		0xcd3e, 0x2807,
1040 		0xcd3f, 0x31a7,
1041 		0xcd40, 0x20c4,
1042 		0xcd41, 0x3c24,
1043 		0xcd42, 0x6724,
1044 		0xcd43, 0x1002,
1045 		0xcd44, 0x2807,
1046 		0xcd45, 0x3187,
1047 		0xcd46, 0x20c4,
1048 		0xcd47, 0x3c24,
1049 		0xcd48, 0x6724,
1050 		0xcd49, 0x1002,
1051 		0xcd4a, 0x2514,
1052 		0xcd4b, 0x3c64,
1053 		0xcd4c, 0x6436,
1054 		0xcd4d, 0xdff4,
1055 		0xcd4e, 0x6436,
1056 		0xcd4f, 0x1002,
1057 		0xcd50, 0x2806,
1058 		0xcd51, 0x3cb6,
1059 		0xcd52, 0xc161,
1060 		0xcd53, 0x6134,
1061 		0xcd54, 0x6135,
1062 		0xcd55, 0x5443,
1063 		0xcd56, 0x303,
1064 		0xcd57, 0x6524,
1065 		0xcd58, 0x00b,
1066 		0xcd59, 0x1002,
1067 		0xcd5a, 0xd019,
1068 		0xcd5b, 0x2104,
1069 		0xcd5c, 0x3c24,
1070 		0xcd5d, 0x2105,
1071 		0xcd5e, 0x3805,
1072 		0xcd5f, 0x6524,
1073 		0xcd60, 0xdff4,
1074 		0xcd61, 0x4005,
1075 		0xcd62, 0x6524,
1076 		0xcd63, 0x2e8d,
1077 		0xcd64, 0x303d,
1078 		0xcd65, 0x5dd3,
1079 		0xcd66, 0x306,
1080 		0xcd67, 0x2ff7,
1081 		0xcd68, 0x38f7,
1082 		0xcd69, 0x60b7,
1083 		0xcd6a, 0xdffd,
1084 		0xcd6b, 0x00a,
1085 		0xcd6c, 0x1002,
1086 		0xcd6d, 0
1087 	};
1088 	int i, err;
1089 
1090 	err = set_phy_regs(phy, regs);
1091 	if (!err && modtype == phy_modtype_twinax_long)
1092 		err = set_phy_regs(phy, preemphasis);
1093 	if (err)
1094 		return err;
1095 
1096 	msleep(50);
1097 
1098 	for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1099 		err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1100 				 twinax_edc[i + 1]);
1101 	if (!err)
1102 		phy->priv = edc_twinax;
1103 	return err;
1104 }
1105 
1106 static int get_module_type(struct cphy *phy)
1107 {
1108 	int v;
1109 
1110 	v = get_phytrans_type(phy);
1111 	if (v == phy_transtype_sfp) {
1112 		/* SFP: see SFF-8472 for below */
1113 
1114 		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3);
1115 		if (v < 0)
1116 			return v;
1117 
1118 		if (v == 0x1)
1119 			return phy_modtype_twinax;
1120 		if (v == 0x10)
1121 			return phy_modtype_sr;
1122 		if (v == 0x20)
1123 			return phy_modtype_lr;
1124 		if (v == 0x40)
1125 			return phy_modtype_lrm;
1126 
1127 		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6);
1128 		if (v < 0)
1129 			return v;
1130 		if (v != 4)
1131 			return phy_modtype_unknown;
1132 
1133 		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10);
1134 		if (v < 0)
1135 			return v;
1136 
1137 		if (v & 0x80) {
1138 			v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
1139 			if (v < 0)
1140 				return v;
1141 			return v > 10 ? phy_modtype_twinax_long :
1142 			    phy_modtype_twinax;
1143 		}
1144 	} else if (v == phy_transtype_xfp) {
1145 		/* XFP: See INF-8077i for details. */
1146 
1147 		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 127);
1148 		if (v < 0)
1149 			return v;
1150 
1151 		if (v != 1) {
1152 			/* XXX: set page select to table 1 yourself */
1153 			return phy_modtype_unknown;
1154 		}
1155 
1156 		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 131);
1157 		if (v < 0)
1158 			return v;
1159 		v &= 0xf0;
1160 		if (v == 0x10)
1161 			return phy_modtype_lrm;
1162 		if (v == 0x40)
1163 			return phy_modtype_lr;
1164 		if (v == 0x80)
1165 			return phy_modtype_sr;
1166 	}
1167 
1168 	return phy_modtype_unknown;
1169 }
1170 
1171 
1172 static int ael2005_intr_enable(struct cphy *phy)
1173 {
1174 	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
1175 	return err ? err : t3_phy_lasi_intr_enable(phy);
1176 }
1177 
1178 static int ael2005_intr_disable(struct cphy *phy)
1179 {
1180 	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
1181 	return err ? err : t3_phy_lasi_intr_disable(phy);
1182 }
1183 
1184 static int ael2005_intr_clear(struct cphy *phy)
1185 {
1186 	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
1187 	return err ? err : t3_phy_lasi_intr_clear(phy);
1188 }
1189 
1190 static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
1191 {
1192 	int v;
1193 	unsigned int stat;
1194 
1195 	v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
1196 	if (v)
1197 		return v;
1198 
1199 	if (stat & (1 << 8))			/* module absent */
1200 		return phy_modtype_none;
1201 
1202 	if (delay_ms)
1203 		msleep(delay_ms);
1204 
1205 	return get_module_type(phy);
1206 }
1207 
1208 static int ael2005_reset(struct cphy *phy, int wait)
1209 {
1210 	static struct reg_val regs0[] = {
1211 		{ MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
1212 		{ MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
1213 		{ MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
1214 		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1215 		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
1216 		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1217 		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
1218 		{ 0, 0, 0, 0 }
1219 	};
1220 	static struct reg_val regs1[] = {
1221 		{ MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
1222 		{ MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
1223 		{ 0, 0, 0, 0 }
1224 	};
1225 
1226 	int err, lasi_ctrl;
1227 
1228 	err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
1229 	if (err)
1230 		return err;
1231 
1232 	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
1233 	if (err)
1234 		return err;
1235 
1236 	msleep(125);
1237 	phy->priv = edc_none;
1238 	err = set_phy_regs(phy, regs0);
1239 	if (err)
1240 		return err;
1241 
1242 	msleep(50);
1243 
1244 	err = ael2005_get_module_type(phy, 0);
1245 	if (err < 0)
1246 		return err;
1247 	phy->modtype = (u8)err;
1248 
1249 	if (err == phy_modtype_none || err == phy_modtype_unknown)
1250 		err = 0;
1251 	else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1252 		err = ael2005_setup_twinax_edc(phy, err);
1253 	else
1254 		err = ael2005_setup_sr_edc(phy);
1255 	if (err)
1256 		return err;
1257 
1258 	err = set_phy_regs(phy, regs1);
1259 	if (err)
1260 		return err;
1261 
1262 	/* reset wipes out interrupts, reenable them if they were on */
1263 	if (lasi_ctrl & 1)
1264 		err = ael2005_intr_enable(phy);
1265 	return err;
1266 }
1267 
1268 static int ael2005_intr_handler(struct cphy *phy)
1269 {
1270 	unsigned int stat;
1271 	int ret, edc_needed, cause = 0;
1272 
1273 	ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
1274 	if (ret)
1275 		return ret;
1276 
1277 	if (stat & AEL2005_MODDET_IRQ) {
1278 		ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
1279 				 0xd00);
1280 		if (ret)
1281 			return ret;
1282 
1283 		/* modules have max 300 ms init time after hot plug */
1284 		ret = ael2005_get_module_type(phy, 300);
1285 		if (ret < 0)
1286 			return ret;
1287 
1288 		phy->modtype = (u8)ret;
1289 		if (ret == phy_modtype_none)
1290 			edc_needed = phy->priv;       /* on unplug retain EDC */
1291 		else if (ret == phy_modtype_twinax ||
1292 			 ret == phy_modtype_twinax_long)
1293 			edc_needed = edc_twinax;
1294 		else
1295 			edc_needed = edc_sr;
1296 
1297 		if (edc_needed != phy->priv) {
1298 			ret = ael2005_reset(phy, 0);
1299 			return ret ? ret : cphy_cause_module_change;
1300 		}
1301 		cause = cphy_cause_module_change;
1302 	}
1303 
1304 	ret = t3_phy_lasi_intr_handler(phy);
1305 	if (ret < 0)
1306 		return ret;
1307 
1308 	ret |= cause;
1309 	if (!ret)
1310 		ret |= cphy_cause_link_change;
1311 	return ret;
1312 }
1313 
1314 #ifdef C99_NOT_SUPPORTED
1315 static struct cphy_ops ael2005_ops = {
1316 	ael2005_reset,
1317 	ael2005_intr_enable,
1318 	ael2005_intr_disable,
1319 	ael2005_intr_clear,
1320 	ael2005_intr_handler,
1321 	NULL,
1322 	NULL,
1323 	NULL,
1324 	NULL,
1325 	NULL,
1326 	get_link_status_r,
1327 	ael1002_power_down,
1328 };
1329 #else
1330 static struct cphy_ops ael2005_ops = {
1331 	.reset           = ael2005_reset,
1332 	.intr_enable     = ael2005_intr_enable,
1333 	.intr_disable    = ael2005_intr_disable,
1334 	.intr_clear      = ael2005_intr_clear,
1335 	.intr_handler    = ael2005_intr_handler,
1336 	.get_link_status = get_link_status_r,
1337 	.power_down      = ael1002_power_down,
1338 };
1339 #endif
1340 
1341 int t3_ael2005_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1342 			const struct mdio_ops *mdio_ops)
1343 {
1344 	int err;
1345 	cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
1346 		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1347 		  SUPPORTED_IRQ, "10GBASE-R");
1348 	msleep(125);
1349 	ael_laser_down(phy, 0);
1350 
1351 	err = ael2005_get_module_type(phy, 0);
1352 	if (err >= 0)
1353 		phy->modtype = err;
1354 
1355 	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
1356 				   1 << 5);
1357 }
1358 
1359 /*
1360  * Get link status for a 10GBASE-X device.
1361  */
1362 static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
1363 			     int *duplex, int *fc)
1364 {
1365 	if (link_ok) {
1366 		unsigned int stat0, stat1, stat2;
1367 		int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
1368 
1369 		if (!err)
1370 			err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
1371 		if (!err)
1372 			err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
1373 		if (err)
1374 			return err;
1375 		*link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
1376 	}
1377 	if (speed)
1378 		*speed = SPEED_10000;
1379 	if (duplex)
1380 		*duplex = DUPLEX_FULL;
1381 	return 0;
1382 }
1383 
1384 #ifdef C99_NOT_SUPPORTED
1385 static struct cphy_ops qt2045_ops = {
1386 	ael1006_reset,
1387 	t3_phy_lasi_intr_enable,
1388 	t3_phy_lasi_intr_disable,
1389 	t3_phy_lasi_intr_clear,
1390 	t3_phy_lasi_intr_handler,
1391 	NULL,
1392 	NULL,
1393 	NULL,
1394 	NULL,
1395 	NULL,
1396 	get_link_status_x,
1397 	ael1006_power_down,
1398 };
1399 #else
1400 static struct cphy_ops qt2045_ops = {
1401 	.reset           = ael1006_reset,
1402 	.intr_enable     = t3_phy_lasi_intr_enable,
1403 	.intr_disable    = t3_phy_lasi_intr_disable,
1404 	.intr_clear      = t3_phy_lasi_intr_clear,
1405 	.intr_handler    = t3_phy_lasi_intr_handler,
1406 	.get_link_status = get_link_status_x,
1407 	.power_down      = ael1006_power_down,
1408 };
1409 #endif
1410 
1411 int t3_qt2045_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1412 		       const struct mdio_ops *mdio_ops)
1413 {
1414 	unsigned int stat;
1415 
1416 	cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops,
1417 		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1418 		  "10GBASE-CX4");
1419 
1420 	/*
1421 	 * Some cards where the PHY is supposed to be at address 0 actually
1422 	 * have it at 1.
1423 	 */
1424 	if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
1425 	    stat == 0xffff)
1426 		phy->addr = 1;
1427 	return 0;
1428 }
1429 
1430 static int xaui_direct_reset(struct cphy *phy, int wait)
1431 {
1432 	return 0;
1433 }
1434 
1435 static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
1436 				       int *speed, int *duplex, int *fc)
1437 {
1438 	if (link_ok) {
1439 		unsigned int status;
1440 
1441 		status = t3_read_reg(phy->adapter,
1442 				     XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
1443 			 t3_read_reg(phy->adapter,
1444 				     XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
1445 			 t3_read_reg(phy->adapter,
1446 				     XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
1447 			 t3_read_reg(phy->adapter,
1448 				     XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
1449 		*link_ok = !(status & F_LOWSIG0);
1450 	}
1451 	if (speed)
1452 		*speed = SPEED_10000;
1453 	if (duplex)
1454 		*duplex = DUPLEX_FULL;
1455 	return 0;
1456 }
1457 
1458 static int xaui_direct_power_down(struct cphy *phy, int enable)
1459 {
1460 	return 0;
1461 }
1462 
1463 #ifdef C99_NOT_SUPPORTED
1464 static struct cphy_ops xaui_direct_ops = {
1465 	xaui_direct_reset,
1466 	ael1002_intr_noop,
1467 	ael1002_intr_noop,
1468 	ael1002_intr_noop,
1469 	ael1002_intr_noop,
1470 	NULL,
1471 	NULL,
1472 	NULL,
1473 	NULL,
1474 	NULL,
1475 	xaui_direct_get_link_status,
1476 	xaui_direct_power_down,
1477 };
1478 #else
1479 static struct cphy_ops xaui_direct_ops = {
1480 	.reset           = xaui_direct_reset,
1481 	.intr_enable     = ael1002_intr_noop,
1482 	.intr_disable    = ael1002_intr_noop,
1483 	.intr_clear      = ael1002_intr_noop,
1484 	.intr_handler    = ael1002_intr_noop,
1485 	.get_link_status = xaui_direct_get_link_status,
1486 	.power_down      = xaui_direct_power_down,
1487 };
1488 #endif
1489 
1490 int t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1491 			    const struct mdio_ops *mdio_ops)
1492 {
1493 	cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
1494 		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1495 		  "10GBASE-CX4");
1496 	return 0;
1497 }
1498