cxgb_ael1002.c revision 189643
1/**************************************************************************
2
3Copyright (c) 2007-2009, Chelsio Inc.
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, 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
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26POSSIBILITY OF SUCH DAMAGE.
27
28***************************************************************************/
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/dev/cxgb/common/cxgb_ael1002.c 189643 2009-03-10 19:22:45Z gnn $");
32
33#include <cxgb_include.h>
34
35#undef msleep
36#define msleep t3_os_sleep
37
38enum {
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
45enum {
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
60enum { edc_none, edc_sr, edc_twinax };
61
62/* PHY module I2C device address */
63enum {
64	MODULE_DEV_ADDR	= 0xa0,
65	SFF_DEV_ADDR	= 0xa2,
66};
67
68/* PHY transceiver type */
69enum {
70	phy_transtype_unknown = 0,
71	phy_transtype_sfp     = 3,
72	phy_transtype_xfp     = 6,
73};
74
75#define AEL2005_MODDET_IRQ 4
76
77struct reg_val {
78	unsigned short mmd_addr;
79	unsigned short reg_addr;
80	unsigned short clear_bits;
81	unsigned short set_bits;
82};
83
84static int get_module_type(struct cphy *phy);
85
86static 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
102static 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
111static 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
139static 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
166static 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
177static 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
215static 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
226static 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
238static 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
258static int ael1002_intr_noop(struct cphy *phy)
259{
260	return 0;
261}
262
263/*
264 * Get link status for a 10GBASE-R device.
265 */
266static 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
289static 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
304static 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
315int 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
333static 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
369static 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
376static 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
391static 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
402int 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
412static 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
709static 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
1106static 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		if (v == 0x10)
1160			return phy_modtype_lrm;
1161		if (v == 0x40)
1162			return phy_modtype_lr;
1163		if (v == 0x80)
1164			return phy_modtype_sr;
1165	}
1166
1167	return phy_modtype_unknown;
1168}
1169
1170
1171static int ael2005_intr_enable(struct cphy *phy)
1172{
1173	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
1174	return err ? err : t3_phy_lasi_intr_enable(phy);
1175}
1176
1177static int ael2005_intr_disable(struct cphy *phy)
1178{
1179	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
1180	return err ? err : t3_phy_lasi_intr_disable(phy);
1181}
1182
1183static int ael2005_intr_clear(struct cphy *phy)
1184{
1185	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
1186	return err ? err : t3_phy_lasi_intr_clear(phy);
1187}
1188
1189static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
1190{
1191	int v;
1192	unsigned int stat;
1193
1194	v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
1195	if (v)
1196		return v;
1197
1198	if (stat & (1 << 8))			/* module absent */
1199		return phy_modtype_none;
1200
1201	if (delay_ms)
1202		msleep(delay_ms);
1203
1204	return get_module_type(phy);
1205}
1206
1207static int ael2005_reset(struct cphy *phy, int wait)
1208{
1209	static struct reg_val regs0[] = {
1210		{ MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
1211		{ MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
1212		{ MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
1213		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1214		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
1215		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1216		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
1217		{ 0, 0, 0, 0 }
1218	};
1219	static struct reg_val regs1[] = {
1220		{ MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
1221		{ MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
1222		{ 0, 0, 0, 0 }
1223	};
1224
1225	int err, lasi_ctrl;
1226
1227	err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
1228	if (err)
1229		return err;
1230
1231	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
1232	if (err)
1233		return err;
1234
1235	msleep(125);
1236	phy->priv = edc_none;
1237	err = set_phy_regs(phy, regs0);
1238	if (err)
1239		return err;
1240
1241	msleep(50);
1242
1243	err = ael2005_get_module_type(phy, 0);
1244	if (err < 0)
1245		return err;
1246	phy->modtype = (u8)err;
1247
1248	if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1249		err = ael2005_setup_twinax_edc(phy, err);
1250	else
1251		err = ael2005_setup_sr_edc(phy);
1252	if (err)
1253		return err;
1254
1255	err = set_phy_regs(phy, regs1);
1256	if (err)
1257		return err;
1258
1259	/* reset wipes out interrupts, reenable them if they were on */
1260	if (lasi_ctrl & 1)
1261		err = ael2005_intr_enable(phy);
1262	return err;
1263}
1264
1265static int ael2005_intr_handler(struct cphy *phy)
1266{
1267	unsigned int stat;
1268	int ret, edc_needed, cause = 0;
1269
1270	ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
1271	if (ret)
1272		return ret;
1273
1274	if (stat & AEL2005_MODDET_IRQ) {
1275		ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
1276				 0xd00);
1277		if (ret)
1278			return ret;
1279
1280		/* modules have max 300 ms init time after hot plug */
1281		ret = ael2005_get_module_type(phy, 300);
1282		if (ret < 0)
1283			return ret;
1284
1285		phy->modtype = (u8)ret;
1286		if (ret == phy_modtype_none)
1287			edc_needed = phy->priv;       /* on unplug retain EDC */
1288		else if (ret == phy_modtype_twinax ||
1289			 ret == phy_modtype_twinax_long)
1290			edc_needed = edc_twinax;
1291		else
1292			edc_needed = edc_sr;
1293
1294		if (edc_needed != phy->priv) {
1295			ret = ael2005_reset(phy, 0);
1296			return ret ? ret : cphy_cause_module_change;
1297		}
1298		cause = cphy_cause_module_change;
1299	}
1300
1301	ret = t3_phy_lasi_intr_handler(phy);
1302	if (ret < 0)
1303		return ret;
1304
1305	ret |= cause;
1306	if (!ret)
1307		ret |= cphy_cause_link_change;
1308	return ret;
1309}
1310
1311#ifdef C99_NOT_SUPPORTED
1312static struct cphy_ops ael2005_ops = {
1313	ael2005_reset,
1314	ael2005_intr_enable,
1315	ael2005_intr_disable,
1316	ael2005_intr_clear,
1317	ael2005_intr_handler,
1318	NULL,
1319	NULL,
1320	NULL,
1321	NULL,
1322	NULL,
1323	get_link_status_r,
1324	ael1002_power_down,
1325};
1326#else
1327static struct cphy_ops ael2005_ops = {
1328	.reset           = ael2005_reset,
1329	.intr_enable     = ael2005_intr_enable,
1330	.intr_disable    = ael2005_intr_disable,
1331	.intr_clear      = ael2005_intr_clear,
1332	.intr_handler    = ael2005_intr_handler,
1333	.get_link_status = get_link_status_r,
1334	.power_down      = ael1002_power_down,
1335};
1336#endif
1337
1338int t3_ael2005_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1339			const struct mdio_ops *mdio_ops)
1340{
1341	int err;
1342	cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
1343		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1344		  SUPPORTED_IRQ, "10GBASE-R");
1345	msleep(125);
1346	ael_laser_down(phy, 0);
1347
1348	err = ael2005_get_module_type(phy, 0);
1349	if (err >= 0)
1350		phy->modtype = err;
1351
1352	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
1353				   1 << 5);
1354}
1355
1356/*
1357 * Get link status for a 10GBASE-X device.
1358 */
1359static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
1360			     int *duplex, int *fc)
1361{
1362	if (link_ok) {
1363		unsigned int stat0, stat1, stat2;
1364		int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
1365
1366		if (!err)
1367			err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
1368		if (!err)
1369			err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
1370		if (err)
1371			return err;
1372		*link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
1373	}
1374	if (speed)
1375		*speed = SPEED_10000;
1376	if (duplex)
1377		*duplex = DUPLEX_FULL;
1378	return 0;
1379}
1380
1381#ifdef C99_NOT_SUPPORTED
1382static struct cphy_ops qt2045_ops = {
1383	ael1006_reset,
1384	t3_phy_lasi_intr_enable,
1385	t3_phy_lasi_intr_disable,
1386	t3_phy_lasi_intr_clear,
1387	t3_phy_lasi_intr_handler,
1388	NULL,
1389	NULL,
1390	NULL,
1391	NULL,
1392	NULL,
1393	get_link_status_x,
1394	ael1006_power_down,
1395};
1396#else
1397static struct cphy_ops qt2045_ops = {
1398	.reset           = ael1006_reset,
1399	.intr_enable     = t3_phy_lasi_intr_enable,
1400	.intr_disable    = t3_phy_lasi_intr_disable,
1401	.intr_clear      = t3_phy_lasi_intr_clear,
1402	.intr_handler    = t3_phy_lasi_intr_handler,
1403	.get_link_status = get_link_status_x,
1404	.power_down      = ael1006_power_down,
1405};
1406#endif
1407
1408int t3_qt2045_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1409		       const struct mdio_ops *mdio_ops)
1410{
1411	unsigned int stat;
1412
1413	cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops,
1414		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1415		  "10GBASE-CX4");
1416
1417	/*
1418	 * Some cards where the PHY is supposed to be at address 0 actually
1419	 * have it at 1.
1420	 */
1421	if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
1422	    stat == 0xffff)
1423		phy->addr = 1;
1424	return 0;
1425}
1426
1427static int xaui_direct_reset(struct cphy *phy, int wait)
1428{
1429	return 0;
1430}
1431
1432static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
1433				       int *speed, int *duplex, int *fc)
1434{
1435	if (link_ok) {
1436		unsigned int status;
1437
1438		status = t3_read_reg(phy->adapter,
1439				     XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
1440			 t3_read_reg(phy->adapter,
1441				     XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
1442			 t3_read_reg(phy->adapter,
1443				     XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
1444			 t3_read_reg(phy->adapter,
1445				     XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
1446		*link_ok = !(status & F_LOWSIG0);
1447	}
1448	if (speed)
1449		*speed = SPEED_10000;
1450	if (duplex)
1451		*duplex = DUPLEX_FULL;
1452	return 0;
1453}
1454
1455static int xaui_direct_power_down(struct cphy *phy, int enable)
1456{
1457	return 0;
1458}
1459
1460#ifdef C99_NOT_SUPPORTED
1461static struct cphy_ops xaui_direct_ops = {
1462	xaui_direct_reset,
1463	ael1002_intr_noop,
1464	ael1002_intr_noop,
1465	ael1002_intr_noop,
1466	ael1002_intr_noop,
1467	NULL,
1468	NULL,
1469	NULL,
1470	NULL,
1471	NULL,
1472	xaui_direct_get_link_status,
1473	xaui_direct_power_down,
1474};
1475#else
1476static struct cphy_ops xaui_direct_ops = {
1477	.reset           = xaui_direct_reset,
1478	.intr_enable     = ael1002_intr_noop,
1479	.intr_disable    = ael1002_intr_noop,
1480	.intr_clear      = ael1002_intr_noop,
1481	.intr_handler    = ael1002_intr_noop,
1482	.get_link_status = xaui_direct_get_link_status,
1483	.power_down      = xaui_direct_power_down,
1484};
1485#endif
1486
1487int t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1488			    const struct mdio_ops *mdio_ops)
1489{
1490	cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
1491		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1492		  "10GBASE-CX4");
1493	return 0;
1494}
1495