cxgb_ael1002.c revision 192540
1224135Sdim/**************************************************************************
2224135Sdim
3353358SdimCopyright (c) 2007-2009, Chelsio Inc.
4353358SdimAll rights reserved.
5353358Sdim
6224135SdimRedistribution and use in source and binary forms, with or without
7224135Sdimmodification, are permitted provided that the following conditions are met:
8224135Sdim
9280031Sdim 1. Redistributions of source code must retain the above copyright notice,
10280031Sdim    this list of conditions and the following disclaimer.
11224135Sdim
12249423Sdim 2. Neither the name of the Chelsio Corporation nor the names of its
13224135Sdim    contributors may be used to endorse or promote products derived from
14276479Sdim    this software without specific prior written permission.
15224135Sdim
16224135SdimTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17224135SdimAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18224135SdimIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19224135SdimARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20224135SdimLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21276479SdimCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22224135SdimSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23224135SdimINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24309124SdimCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25224135SdimARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26224135SdimPOSSIBILITY OF SUCH DAMAGE.
27224135Sdim
28224135Sdim***************************************************************************/
29276479Sdim
30224135Sdim#include <sys/cdefs.h>
31224135Sdim__FBSDID("$FreeBSD: head/sys/dev/cxgb/common/cxgb_ael1002.c 192540 2009-05-21 15:08:03Z gnn $");
32309124Sdim
33224135Sdim#include <cxgb_include.h>
34224135Sdim
35234353Sdim#undef msleep
36234353Sdim#define msleep t3_os_sleep
37234353Sdim
38276479Sdimenum {
39280031Sdim	PMD_RSD     = 10,   /* PMA/PMD receive signal detect register */
40280031Sdim	PCS_STAT1_X = 24,   /* 10GBASE-X PCS status 1 register */
41234353Sdim	PCS_STAT1_R = 32,   /* 10GBASE-R PCS status 1 register */
42234353Sdim	XS_LN_STAT  = 24    /* XS lane status register */
43224135Sdim};
44224135Sdim
45226633Sdimenum {
46226633Sdim	AEL100X_TX_DISABLE  = 9,
47224135Sdim	AEL100X_TX_CONFIG1  = 0xc002,
48276479Sdim	AEL1002_PWR_DOWN_HI = 0xc011,
49224135Sdim	AEL1002_PWR_DOWN_LO = 0xc012,
50224135Sdim	AEL1002_XFI_EQL     = 0xc015,
51309124Sdim	AEL1002_LB_EN       = 0xc017,
52309124Sdim	AEL_OPT_SETTINGS    = 0xc017,
53226633Sdim	AEL_I2C_CTRL        = 0xc30a,
54226633Sdim	AEL_I2C_DATA        = 0xc30b,
55224135Sdim	AEL_I2C_STAT        = 0xc30c,
56224135Sdim	AEL2005_GPIO_CTRL   = 0xc214,
57341825Sdim	AEL2005_GPIO_STAT   = 0xc215,
58234353Sdim};
59234353Sdim
60261991Sdimenum { edc_none, edc_sr, edc_twinax };
61234353Sdim
62234353Sdim/* PHY module I2C device address */
63234353Sdimenum {
64309124Sdim	MODULE_DEV_ADDR	= 0xa0,
65309124Sdim	SFF_DEV_ADDR	= 0xa2,
66234353Sdim};
67234353Sdim
68280031Sdim/* PHY transceiver type */
69280031Sdimenum {
70276479Sdim	phy_transtype_unknown = 0,
71234353Sdim	phy_transtype_sfp     = 3,
72234353Sdim	phy_transtype_xfp     = 6,
73224135Sdim};
74224135Sdim
75224135Sdim#define AEL2005_MODDET_IRQ 4
76224135Sdim
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		v &= 0xf0;
1160		if (v == 0x10)
1161			return phy_modtype_lrm;
1162		if (v == 0x40)
1163			return phy_modtype_lr;
1164		if (v == 0x80)
1165			return phy_modtype_sr;
1166	}
1167
1168	return phy_modtype_unknown;
1169}
1170
1171
1172static int ael2005_intr_enable(struct cphy *phy)
1173{
1174	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
1175	return err ? err : t3_phy_lasi_intr_enable(phy);
1176}
1177
1178static int ael2005_intr_disable(struct cphy *phy)
1179{
1180	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
1181	return err ? err : t3_phy_lasi_intr_disable(phy);
1182}
1183
1184static int ael2005_intr_clear(struct cphy *phy)
1185{
1186	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
1187	return err ? err : t3_phy_lasi_intr_clear(phy);
1188}
1189
1190static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
1191{
1192	int v;
1193	unsigned int stat;
1194
1195	v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
1196	if (v)
1197		return v;
1198
1199	if (stat & (1 << 8))			/* module absent */
1200		return phy_modtype_none;
1201
1202	if (delay_ms)
1203		msleep(delay_ms);
1204
1205	return get_module_type(phy);
1206}
1207
1208static int ael2005_reset(struct cphy *phy, int wait)
1209{
1210	static struct reg_val regs0[] = {
1211		{ MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
1212		{ MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
1213		{ MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
1214		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1215		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
1216		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1217		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
1218		{ 0, 0, 0, 0 }
1219	};
1220	static struct reg_val regs1[] = {
1221		{ MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
1222		{ MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
1223		{ 0, 0, 0, 0 }
1224	};
1225
1226	int err, lasi_ctrl;
1227
1228	err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
1229	if (err)
1230		return err;
1231
1232	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
1233	if (err)
1234		return err;
1235
1236	msleep(125);
1237	phy->priv = edc_none;
1238	err = set_phy_regs(phy, regs0);
1239	if (err)
1240		return err;
1241
1242	msleep(50);
1243
1244	err = ael2005_get_module_type(phy, 0);
1245	if (err < 0)
1246		return err;
1247	phy->modtype = (u8)err;
1248
1249	if (err == phy_modtype_none || err == phy_modtype_unknown)
1250		err = 0;
1251	else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1252		err = ael2005_setup_twinax_edc(phy, err);
1253	else
1254		err = ael2005_setup_sr_edc(phy);
1255	if (err)
1256		return err;
1257
1258	err = set_phy_regs(phy, regs1);
1259	if (err)
1260		return err;
1261
1262	/* reset wipes out interrupts, reenable them if they were on */
1263	if (lasi_ctrl & 1)
1264		err = ael2005_intr_enable(phy);
1265	return err;
1266}
1267
1268static int ael2005_intr_handler(struct cphy *phy)
1269{
1270	unsigned int stat;
1271	int ret, edc_needed, cause = 0;
1272
1273	ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
1274	if (ret)
1275		return ret;
1276
1277	if (stat & AEL2005_MODDET_IRQ) {
1278		ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
1279				 0xd00);
1280		if (ret)
1281			return ret;
1282
1283		/* modules have max 300 ms init time after hot plug */
1284		ret = ael2005_get_module_type(phy, 300);
1285		if (ret < 0)
1286			return ret;
1287
1288		phy->modtype = (u8)ret;
1289		if (ret == phy_modtype_none)
1290			edc_needed = phy->priv;       /* on unplug retain EDC */
1291		else if (ret == phy_modtype_twinax ||
1292			 ret == phy_modtype_twinax_long)
1293			edc_needed = edc_twinax;
1294		else
1295			edc_needed = edc_sr;
1296
1297		if (edc_needed != phy->priv) {
1298			ret = ael2005_reset(phy, 0);
1299			return ret ? ret : cphy_cause_module_change;
1300		}
1301		cause = cphy_cause_module_change;
1302	}
1303
1304	ret = t3_phy_lasi_intr_handler(phy);
1305	if (ret < 0)
1306		return ret;
1307
1308	ret |= cause;
1309	if (!ret)
1310		ret |= cphy_cause_link_change;
1311	return ret;
1312}
1313
1314#ifdef C99_NOT_SUPPORTED
1315static struct cphy_ops ael2005_ops = {
1316	ael2005_reset,
1317	ael2005_intr_enable,
1318	ael2005_intr_disable,
1319	ael2005_intr_clear,
1320	ael2005_intr_handler,
1321	NULL,
1322	NULL,
1323	NULL,
1324	NULL,
1325	NULL,
1326	get_link_status_r,
1327	ael1002_power_down,
1328};
1329#else
1330static struct cphy_ops ael2005_ops = {
1331	.reset           = ael2005_reset,
1332	.intr_enable     = ael2005_intr_enable,
1333	.intr_disable    = ael2005_intr_disable,
1334	.intr_clear      = ael2005_intr_clear,
1335	.intr_handler    = ael2005_intr_handler,
1336	.get_link_status = get_link_status_r,
1337	.power_down      = ael1002_power_down,
1338};
1339#endif
1340
1341int t3_ael2005_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1342			const struct mdio_ops *mdio_ops)
1343{
1344	int err;
1345	cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
1346		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1347		  SUPPORTED_IRQ, "10GBASE-R");
1348	msleep(125);
1349	ael_laser_down(phy, 0);
1350
1351	err = ael2005_get_module_type(phy, 0);
1352	if (err >= 0)
1353		phy->modtype = err;
1354
1355	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
1356				   1 << 5);
1357}
1358
1359/*
1360 * Get link status for a 10GBASE-X device.
1361 */
1362static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
1363			     int *duplex, int *fc)
1364{
1365	if (link_ok) {
1366		unsigned int stat0, stat1, stat2;
1367		int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
1368
1369		if (!err)
1370			err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
1371		if (!err)
1372			err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
1373		if (err)
1374			return err;
1375		*link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
1376	}
1377	if (speed)
1378		*speed = SPEED_10000;
1379	if (duplex)
1380		*duplex = DUPLEX_FULL;
1381	return 0;
1382}
1383
1384#ifdef C99_NOT_SUPPORTED
1385static struct cphy_ops qt2045_ops = {
1386	ael1006_reset,
1387	t3_phy_lasi_intr_enable,
1388	t3_phy_lasi_intr_disable,
1389	t3_phy_lasi_intr_clear,
1390	t3_phy_lasi_intr_handler,
1391	NULL,
1392	NULL,
1393	NULL,
1394	NULL,
1395	NULL,
1396	get_link_status_x,
1397	ael1006_power_down,
1398};
1399#else
1400static struct cphy_ops qt2045_ops = {
1401	.reset           = ael1006_reset,
1402	.intr_enable     = t3_phy_lasi_intr_enable,
1403	.intr_disable    = t3_phy_lasi_intr_disable,
1404	.intr_clear      = t3_phy_lasi_intr_clear,
1405	.intr_handler    = t3_phy_lasi_intr_handler,
1406	.get_link_status = get_link_status_x,
1407	.power_down      = ael1006_power_down,
1408};
1409#endif
1410
1411int t3_qt2045_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1412		       const struct mdio_ops *mdio_ops)
1413{
1414	unsigned int stat;
1415
1416	cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops,
1417		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1418		  "10GBASE-CX4");
1419
1420	/*
1421	 * Some cards where the PHY is supposed to be at address 0 actually
1422	 * have it at 1.
1423	 */
1424	if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
1425	    stat == 0xffff)
1426		phy->addr = 1;
1427	return 0;
1428}
1429
1430static int xaui_direct_reset(struct cphy *phy, int wait)
1431{
1432	return 0;
1433}
1434
1435static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
1436				       int *speed, int *duplex, int *fc)
1437{
1438	if (link_ok) {
1439		unsigned int status;
1440
1441		status = t3_read_reg(phy->adapter,
1442				     XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
1443			 t3_read_reg(phy->adapter,
1444				     XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
1445			 t3_read_reg(phy->adapter,
1446				     XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
1447			 t3_read_reg(phy->adapter,
1448				     XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
1449		*link_ok = !(status & F_LOWSIG0);
1450	}
1451	if (speed)
1452		*speed = SPEED_10000;
1453	if (duplex)
1454		*duplex = DUPLEX_FULL;
1455	return 0;
1456}
1457
1458static int xaui_direct_power_down(struct cphy *phy, int enable)
1459{
1460	return 0;
1461}
1462
1463#ifdef C99_NOT_SUPPORTED
1464static struct cphy_ops xaui_direct_ops = {
1465	xaui_direct_reset,
1466	ael1002_intr_noop,
1467	ael1002_intr_noop,
1468	ael1002_intr_noop,
1469	ael1002_intr_noop,
1470	NULL,
1471	NULL,
1472	NULL,
1473	NULL,
1474	NULL,
1475	xaui_direct_get_link_status,
1476	xaui_direct_power_down,
1477};
1478#else
1479static struct cphy_ops xaui_direct_ops = {
1480	.reset           = xaui_direct_reset,
1481	.intr_enable     = ael1002_intr_noop,
1482	.intr_disable    = ael1002_intr_noop,
1483	.intr_clear      = ael1002_intr_noop,
1484	.intr_handler    = ael1002_intr_noop,
1485	.get_link_status = xaui_direct_get_link_status,
1486	.power_down      = xaui_direct_power_down,
1487};
1488#endif
1489
1490int t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
1491			    const struct mdio_ops *mdio_ops)
1492{
1493	cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
1494		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
1495		  "10GBASE-CX4");
1496	return 0;
1497}
1498