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