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