cxgb_ael1002.c revision 204921
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 204921 2010-03-09 19:57:44Z np $");
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
49	AEL1002_PWR_DOWN_HI = 0xc011,
50	AEL1002_PWR_DOWN_LO = 0xc012,
51	AEL1002_XFI_EQL     = 0xc015,
52	AEL1002_LB_EN       = 0xc017,
53
54	AEL_OPT_SETTINGS    = 0xc017,
55	AEL_I2C_CTRL        = 0xc30a,
56	AEL_I2C_DATA        = 0xc30b,
57	AEL_I2C_STAT        = 0xc30c,
58
59	AEL2005_GPIO_CTRL   = 0xc214,
60	AEL2005_GPIO_STAT   = 0xc215,
61
62	AEL2020_GPIO_INTR   = 0xc103,
63	AEL2020_GPIO_CTRL   = 0xc108,
64	AEL2020_GPIO_STAT   = 0xc10c,
65	AEL2020_GPIO_CFG    = 0xc110,
66
67	AEL2020_GPIO_SDA    = 0,
68	AEL2020_GPIO_MODDET = 1,
69	AEL2020_GPIO_0      = 3,
70	AEL2020_GPIO_1      = 2,
71	AEL2020_GPIO_LSTAT  = AEL2020_GPIO_1,
72};
73
74enum { edc_none, edc_sr, edc_twinax };
75
76/* PHY module I2C device address */
77enum {
78	MODULE_DEV_ADDR	= 0xa0,
79	SFF_DEV_ADDR	= 0xa2,
80};
81
82/* PHY transceiver type */
83enum {
84	phy_transtype_unknown = 0,
85	phy_transtype_sfp     = 3,
86	phy_transtype_xfp     = 6,
87};
88
89#define AEL2005_MODDET_IRQ 4
90
91struct reg_val {
92	unsigned short mmd_addr;
93	unsigned short reg_addr;
94	unsigned short clear_bits;
95	unsigned short set_bits;
96};
97
98static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms);
99
100static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
101{
102	int err;
103
104	for (err = 0; rv->mmd_addr && !err; rv++) {
105		if (rv->clear_bits == 0xffff)
106			err = mdio_write(phy, rv->mmd_addr, rv->reg_addr,
107					 rv->set_bits);
108		else
109			err = t3_mdio_change_bits(phy, rv->mmd_addr,
110						  rv->reg_addr, rv->clear_bits,
111						  rv->set_bits);
112	}
113	return err;
114}
115
116static void ael100x_txon(struct cphy *phy)
117{
118	int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
119
120	msleep(100);
121	t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
122	msleep(30);
123}
124
125/*
126 * Read an 8-bit word from a device attached to the PHY's i2c bus.
127 */
128static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
129{
130	int i, err;
131	unsigned int stat, data;
132
133	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
134			 (dev_addr << 8) | (1 << 8) | word_addr);
135	if (err)
136		return err;
137
138	for (i = 0; i < 200; i++) {
139		msleep(1);
140		err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
141		if (err)
142			return err;
143		if ((stat & 3) == 1) {
144			err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA,
145					&data);
146			if (err)
147				return err;
148			return data >> 8;
149		}
150	}
151	CH_WARN(phy->adapter, "PHY %u i2c read of dev.addr %x.%x timed out\n",
152		phy->addr, dev_addr, word_addr);
153	return -ETIMEDOUT;
154}
155
156/*
157 * Write an 8-bit word to a device attached to the PHY's i2c bus.
158 */
159static int ael_i2c_wr(struct cphy *phy, int dev_addr, int word_addr, int data)
160{
161	int i, err;
162	unsigned int stat;
163
164	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, data);
165	if (err)
166		return err;
167
168	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL,
169			 (dev_addr << 8) | word_addr);
170	if (err)
171		return err;
172
173	for (i = 0; i < 200; i++) {
174		msleep(1);
175		err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat);
176		if (err)
177			return err;
178		if ((stat & 3) == 1)
179			return 0;
180	}
181	CH_WARN(phy->adapter, "PHY %u i2c Write of dev.addr %x.%x = %#x timed out\n",
182		phy->addr, dev_addr, word_addr, data);
183	return -ETIMEDOUT;
184}
185
186static int get_phytrans_type(struct cphy *phy)
187{
188	int v;
189
190	v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0);
191	if (v < 0)
192		return phy_transtype_unknown;
193
194	return v;
195}
196
197static int ael_laser_down(struct cphy *phy, int enable)
198{
199	int v, dev_addr;
200
201	v = get_phytrans_type(phy);
202	if (v < 0)
203		return v;
204
205	if (v == phy_transtype_sfp) {
206		/* Check SFF Soft TX disable is supported */
207		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 93);
208		if (v < 0)
209			return v;
210
211		v &= 0x40;
212		if (!v)
213			return v;
214
215		dev_addr = SFF_DEV_ADDR;
216	} else if (v == phy_transtype_xfp)
217		dev_addr = MODULE_DEV_ADDR;
218	else
219		return v;
220
221	v = ael_i2c_rd(phy, dev_addr, 110);
222	if (v < 0)
223		return v;
224
225	if (enable)
226		v |= 0x40;
227	else
228		v &= ~0x40;
229
230	v = ael_i2c_wr(phy, dev_addr, 110, v);
231
232	return v;
233}
234
235static int ael1002_power_down(struct cphy *phy, int enable)
236{
237	int err;
238
239	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable);
240	if (!err)
241		err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
242					  BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
243	return err;
244}
245
246static int ael1002_get_module_type(struct cphy *phy, int delay_ms)
247{
248	int v;
249
250	if (delay_ms)
251		msleep(delay_ms);
252
253	v = ael2xxx_get_module_type(phy, delay_ms);
254
255	return (v == -ETIMEDOUT ? phy_modtype_none : v);
256}
257
258static int ael1002_reset(struct cphy *phy, int wait)
259{
260	int err;
261
262	if ((err = ael1002_power_down(phy, 0)) ||
263	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) ||
264	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) ||
265	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) ||
266	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) ||
267	    (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
268				       0, 1 << 5)))
269		return err;
270
271	err = ael1002_get_module_type(phy, 300);
272	if (err >= 0)
273		phy->modtype = err;
274
275	return 0;
276}
277
278static int ael1002_intr_noop(struct cphy *phy)
279{
280	return 0;
281}
282
283/*
284 * Get link status for a 10GBASE-R device.
285 */
286static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed,
287			     int *duplex, int *fc)
288{
289	if (link_ok) {
290		unsigned int stat0, stat1, stat2;
291		int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
292
293		if (!err)
294			err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1);
295		if (!err)
296			err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
297		if (err)
298			return err;
299		*link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
300	}
301	if (speed)
302		*speed = SPEED_10000;
303	if (duplex)
304		*duplex = DUPLEX_FULL;
305	return 0;
306}
307
308#ifdef C99_NOT_SUPPORTED
309static struct cphy_ops ael1002_ops = {
310	ael1002_reset,
311	ael1002_intr_noop,
312	ael1002_intr_noop,
313	ael1002_intr_noop,
314	ael1002_intr_noop,
315	NULL,
316	NULL,
317	NULL,
318	NULL,
319	NULL,
320	get_link_status_r,
321	ael1002_power_down,
322};
323#else
324static struct cphy_ops ael1002_ops = {
325	.reset           = ael1002_reset,
326	.intr_enable     = ael1002_intr_noop,
327	.intr_disable    = ael1002_intr_noop,
328	.intr_clear      = ael1002_intr_noop,
329	.intr_handler    = ael1002_intr_noop,
330	.get_link_status = get_link_status_r,
331	.power_down      = ael1002_power_down,
332};
333#endif
334
335int t3_ael1002_phy_prep(pinfo_t *pinfo, int phy_addr,
336			const struct mdio_ops *mdio_ops)
337{
338	int err;
339	struct cphy *phy = &pinfo->phy;
340
341	cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael1002_ops, mdio_ops,
342		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
343		  "10GBASE-R");
344	ael100x_txon(phy);
345	ael_laser_down(phy, 0);
346
347	err = ael1002_get_module_type(phy, 0);
348	if (err >= 0)
349		phy->modtype = err;
350
351	return 0;
352}
353
354static int ael1006_reset(struct cphy *phy, int wait)
355{
356	int err;
357
358	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
359	if (err)
360		return err;
361
362	t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
363			 F_GPIO6_OUT_VAL, 0);
364
365	msleep(125);
366
367	t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
368			 F_GPIO6_OUT_VAL, F_GPIO6_OUT_VAL);
369
370	msleep(125);
371
372	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
373	if (err)
374		return err;
375
376	msleep(125);
377
378	err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 1);
379	if (err)
380		return err;
381
382	msleep(125);
383
384	err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 0);
385
386	return err;
387
388}
389
390#ifdef C99_NOT_SUPPORTED
391static struct cphy_ops ael1006_ops = {
392	ael1006_reset,
393	t3_phy_lasi_intr_enable,
394	t3_phy_lasi_intr_disable,
395	t3_phy_lasi_intr_clear,
396	t3_phy_lasi_intr_handler,
397	NULL,
398	NULL,
399	NULL,
400	NULL,
401	NULL,
402	get_link_status_r,
403	ael1002_power_down,
404};
405#else
406static struct cphy_ops ael1006_ops = {
407	.reset           = ael1006_reset,
408	.intr_enable     = t3_phy_lasi_intr_enable,
409	.intr_disable    = t3_phy_lasi_intr_disable,
410	.intr_clear      = t3_phy_lasi_intr_clear,
411	.intr_handler    = t3_phy_lasi_intr_handler,
412	.get_link_status = get_link_status_r,
413	.power_down      = ael1002_power_down,
414};
415#endif
416
417int t3_ael1006_phy_prep(pinfo_t *pinfo, int phy_addr,
418			const struct mdio_ops *mdio_ops)
419{
420	struct cphy *phy = &pinfo->phy;
421
422	cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael1006_ops, mdio_ops,
423		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
424		  "10GBASE-SR");
425	phy->modtype = phy_modtype_sr;
426	ael100x_txon(phy);
427	return 0;
428}
429
430/*
431 * Decode our module type.
432 */
433static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms)
434{
435	int v;
436
437	if (delay_ms)
438		msleep(delay_ms);
439
440	v = get_phytrans_type(phy);
441	if (v == phy_transtype_sfp) {
442		/* SFP: see SFF-8472 for below */
443
444		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3);
445		if (v < 0)
446			return v;
447
448		if (v == 0x1)
449			goto twinax;
450		if (v == 0x10)
451			return phy_modtype_sr;
452		if (v == 0x20)
453			return phy_modtype_lr;
454		if (v == 0x40)
455			return phy_modtype_lrm;
456
457		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 8);
458		if (v < 0)
459			return v;
460		if (v == 4) {
461			v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 60);
462			if (v < 0)
463				return v;
464			if (v & 0x1)
465				goto twinax;
466		}
467
468		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6);
469		if (v < 0)
470			return v;
471		if (v != 4)
472			return phy_modtype_unknown;
473
474		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10);
475		if (v < 0)
476			return v;
477
478		if (v & 0x80) {
479twinax:
480			v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
481			if (v < 0)
482				return v;
483			return v > 10 ? phy_modtype_twinax_long :
484			    phy_modtype_twinax;
485		}
486	} else if (v == phy_transtype_xfp) {
487		/* XFP: See INF-8077i for details. */
488
489		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 127);
490		if (v < 0)
491			return v;
492
493		if (v != 1) {
494			/* XXX: set page select to table 1 yourself */
495			return phy_modtype_unknown;
496		}
497
498		v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 131);
499		if (v < 0)
500			return v;
501		v &= 0xf0;
502		if (v == 0x10)
503			return phy_modtype_lrm;
504		if (v == 0x40)
505			return phy_modtype_lr;
506		if (v == 0x80)
507			return phy_modtype_sr;
508	}
509
510	return phy_modtype_unknown;
511}
512
513/*
514 * Code to support the Aeluros/NetLogic 2005 10Gb PHY.
515 */
516static int ael2005_setup_sr_edc(struct cphy *phy)
517{
518	static struct reg_val regs[] = {
519		{ MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 },
520		{ MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a },
521		{ MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 },
522		{ 0, 0, 0, 0 }
523	};
524	static u16 sr_edc[] = {
525		0xcc00, 0x2ff4,
526		0xcc01, 0x3cd4,
527		0xcc02, 0x2015,
528		0xcc03, 0x3105,
529		0xcc04, 0x6524,
530		0xcc05, 0x27ff,
531		0xcc06, 0x300f,
532		0xcc07, 0x2c8b,
533		0xcc08, 0x300b,
534		0xcc09, 0x4009,
535		0xcc0a, 0x400e,
536		0xcc0b, 0x2f72,
537		0xcc0c, 0x3002,
538		0xcc0d, 0x1002,
539		0xcc0e, 0x2172,
540		0xcc0f, 0x3012,
541		0xcc10, 0x1002,
542		0xcc11, 0x25d2,
543		0xcc12, 0x3012,
544		0xcc13, 0x1002,
545		0xcc14, 0xd01e,
546		0xcc15, 0x27d2,
547		0xcc16, 0x3012,
548		0xcc17, 0x1002,
549		0xcc18, 0x2004,
550		0xcc19, 0x3c84,
551		0xcc1a, 0x6436,
552		0xcc1b, 0x2007,
553		0xcc1c, 0x3f87,
554		0xcc1d, 0x8676,
555		0xcc1e, 0x40b7,
556		0xcc1f, 0xa746,
557		0xcc20, 0x4047,
558		0xcc21, 0x5673,
559		0xcc22, 0x2982,
560		0xcc23, 0x3002,
561		0xcc24, 0x13d2,
562		0xcc25, 0x8bbd,
563		0xcc26, 0x2862,
564		0xcc27, 0x3012,
565		0xcc28, 0x1002,
566		0xcc29, 0x2092,
567		0xcc2a, 0x3012,
568		0xcc2b, 0x1002,
569		0xcc2c, 0x5cc3,
570		0xcc2d, 0x314,
571		0xcc2e, 0x2942,
572		0xcc2f, 0x3002,
573		0xcc30, 0x1002,
574		0xcc31, 0xd019,
575		0xcc32, 0x2032,
576		0xcc33, 0x3012,
577		0xcc34, 0x1002,
578		0xcc35, 0x2a04,
579		0xcc36, 0x3c74,
580		0xcc37, 0x6435,
581		0xcc38, 0x2fa4,
582		0xcc39, 0x3cd4,
583		0xcc3a, 0x6624,
584		0xcc3b, 0x5563,
585		0xcc3c, 0x2d42,
586		0xcc3d, 0x3002,
587		0xcc3e, 0x13d2,
588		0xcc3f, 0x464d,
589		0xcc40, 0x2862,
590		0xcc41, 0x3012,
591		0xcc42, 0x1002,
592		0xcc43, 0x2032,
593		0xcc44, 0x3012,
594		0xcc45, 0x1002,
595		0xcc46, 0x2fb4,
596		0xcc47, 0x3cd4,
597		0xcc48, 0x6624,
598		0xcc49, 0x5563,
599		0xcc4a, 0x2d42,
600		0xcc4b, 0x3002,
601		0xcc4c, 0x13d2,
602		0xcc4d, 0x2ed2,
603		0xcc4e, 0x3002,
604		0xcc4f, 0x1002,
605		0xcc50, 0x2fd2,
606		0xcc51, 0x3002,
607		0xcc52, 0x1002,
608		0xcc53, 0x004,
609		0xcc54, 0x2942,
610		0xcc55, 0x3002,
611		0xcc56, 0x1002,
612		0xcc57, 0x2092,
613		0xcc58, 0x3012,
614		0xcc59, 0x1002,
615		0xcc5a, 0x5cc3,
616		0xcc5b, 0x317,
617		0xcc5c, 0x2f72,
618		0xcc5d, 0x3002,
619		0xcc5e, 0x1002,
620		0xcc5f, 0x2942,
621		0xcc60, 0x3002,
622		0xcc61, 0x1002,
623		0xcc62, 0x22cd,
624		0xcc63, 0x301d,
625		0xcc64, 0x2862,
626		0xcc65, 0x3012,
627		0xcc66, 0x1002,
628		0xcc67, 0x2ed2,
629		0xcc68, 0x3002,
630		0xcc69, 0x1002,
631		0xcc6a, 0x2d72,
632		0xcc6b, 0x3002,
633		0xcc6c, 0x1002,
634		0xcc6d, 0x628f,
635		0xcc6e, 0x2112,
636		0xcc6f, 0x3012,
637		0xcc70, 0x1002,
638		0xcc71, 0x5aa3,
639		0xcc72, 0x2dc2,
640		0xcc73, 0x3002,
641		0xcc74, 0x1312,
642		0xcc75, 0x6f72,
643		0xcc76, 0x1002,
644		0xcc77, 0x2807,
645		0xcc78, 0x31a7,
646		0xcc79, 0x20c4,
647		0xcc7a, 0x3c24,
648		0xcc7b, 0x6724,
649		0xcc7c, 0x1002,
650		0xcc7d, 0x2807,
651		0xcc7e, 0x3187,
652		0xcc7f, 0x20c4,
653		0xcc80, 0x3c24,
654		0xcc81, 0x6724,
655		0xcc82, 0x1002,
656		0xcc83, 0x2514,
657		0xcc84, 0x3c64,
658		0xcc85, 0x6436,
659		0xcc86, 0xdff4,
660		0xcc87, 0x6436,
661		0xcc88, 0x1002,
662		0xcc89, 0x40a4,
663		0xcc8a, 0x643c,
664		0xcc8b, 0x4016,
665		0xcc8c, 0x8c6c,
666		0xcc8d, 0x2b24,
667		0xcc8e, 0x3c24,
668		0xcc8f, 0x6435,
669		0xcc90, 0x1002,
670		0xcc91, 0x2b24,
671		0xcc92, 0x3c24,
672		0xcc93, 0x643a,
673		0xcc94, 0x4025,
674		0xcc95, 0x8a5a,
675		0xcc96, 0x1002,
676		0xcc97, 0x2731,
677		0xcc98, 0x3011,
678		0xcc99, 0x1001,
679		0xcc9a, 0xc7a0,
680		0xcc9b, 0x100,
681		0xcc9c, 0xc502,
682		0xcc9d, 0x53ac,
683		0xcc9e, 0xc503,
684		0xcc9f, 0xd5d5,
685		0xcca0, 0xc600,
686		0xcca1, 0x2a6d,
687		0xcca2, 0xc601,
688		0xcca3, 0x2a4c,
689		0xcca4, 0xc602,
690		0xcca5, 0x111,
691		0xcca6, 0xc60c,
692		0xcca7, 0x5900,
693		0xcca8, 0xc710,
694		0xcca9, 0x700,
695		0xccaa, 0xc718,
696		0xccab, 0x700,
697		0xccac, 0xc720,
698		0xccad, 0x4700,
699		0xccae, 0xc801,
700		0xccaf, 0x7f50,
701		0xccb0, 0xc802,
702		0xccb1, 0x7760,
703		0xccb2, 0xc803,
704		0xccb3, 0x7fce,
705		0xccb4, 0xc804,
706		0xccb5, 0x5700,
707		0xccb6, 0xc805,
708		0xccb7, 0x5f11,
709		0xccb8, 0xc806,
710		0xccb9, 0x4751,
711		0xccba, 0xc807,
712		0xccbb, 0x57e1,
713		0xccbc, 0xc808,
714		0xccbd, 0x2700,
715		0xccbe, 0xc809,
716		0xccbf, 0x000,
717		0xccc0, 0xc821,
718		0xccc1, 0x002,
719		0xccc2, 0xc822,
720		0xccc3, 0x014,
721		0xccc4, 0xc832,
722		0xccc5, 0x1186,
723		0xccc6, 0xc847,
724		0xccc7, 0x1e02,
725		0xccc8, 0xc013,
726		0xccc9, 0xf341,
727		0xccca, 0xc01a,
728		0xcccb, 0x446,
729		0xcccc, 0xc024,
730		0xcccd, 0x1000,
731		0xccce, 0xc025,
732		0xcccf, 0xa00,
733		0xccd0, 0xc026,
734		0xccd1, 0xc0c,
735		0xccd2, 0xc027,
736		0xccd3, 0xc0c,
737		0xccd4, 0xc029,
738		0xccd5, 0x0a0,
739		0xccd6, 0xc030,
740		0xccd7, 0xa00,
741		0xccd8, 0xc03c,
742		0xccd9, 0x01c,
743		0xccda, 0xc005,
744		0xccdb, 0x7a06,
745		0xccdc, 0x000,
746		0xccdd, 0x2731,
747		0xccde, 0x3011,
748		0xccdf, 0x1001,
749		0xcce0, 0xc620,
750		0xcce1, 0x000,
751		0xcce2, 0xc621,
752		0xcce3, 0x03f,
753		0xcce4, 0xc622,
754		0xcce5, 0x000,
755		0xcce6, 0xc623,
756		0xcce7, 0x000,
757		0xcce8, 0xc624,
758		0xcce9, 0x000,
759		0xccea, 0xc625,
760		0xcceb, 0x000,
761		0xccec, 0xc627,
762		0xcced, 0x000,
763		0xccee, 0xc628,
764		0xccef, 0x000,
765		0xccf0, 0xc62c,
766		0xccf1, 0x000,
767		0xccf2, 0x000,
768		0xccf3, 0x2806,
769		0xccf4, 0x3cb6,
770		0xccf5, 0xc161,
771		0xccf6, 0x6134,
772		0xccf7, 0x6135,
773		0xccf8, 0x5443,
774		0xccf9, 0x303,
775		0xccfa, 0x6524,
776		0xccfb, 0x00b,
777		0xccfc, 0x1002,
778		0xccfd, 0x2104,
779		0xccfe, 0x3c24,
780		0xccff, 0x2105,
781		0xcd00, 0x3805,
782		0xcd01, 0x6524,
783		0xcd02, 0xdff4,
784		0xcd03, 0x4005,
785		0xcd04, 0x6524,
786		0xcd05, 0x1002,
787		0xcd06, 0x5dd3,
788		0xcd07, 0x306,
789		0xcd08, 0x2ff7,
790		0xcd09, 0x38f7,
791		0xcd0a, 0x60b7,
792		0xcd0b, 0xdffd,
793		0xcd0c, 0x00a,
794		0xcd0d, 0x1002,
795		0xcd0e, 0
796	};
797	int i, err;
798
799	err = set_phy_regs(phy, regs);
800	if (err)
801		return err;
802
803	msleep(50);
804
805	for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
806		err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i],
807				 sr_edc[i + 1]);
808	if (!err)
809		phy->priv = edc_sr;
810	return err;
811}
812
813static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype)
814{
815	static struct reg_val regs[] = {
816		{ MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 },
817		{ 0, 0, 0, 0 }
818	};
819	static struct reg_val preemphasis[] = {
820		{ MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 },
821		{ MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 },
822		{ 0, 0, 0, 0 }
823	};
824	static u16 twinax_edc[] = {
825		0xcc00, 0x4009,
826		0xcc01, 0x27ff,
827		0xcc02, 0x300f,
828		0xcc03, 0x40aa,
829		0xcc04, 0x401c,
830		0xcc05, 0x401e,
831		0xcc06, 0x2ff4,
832		0xcc07, 0x3cd4,
833		0xcc08, 0x2035,
834		0xcc09, 0x3145,
835		0xcc0a, 0x6524,
836		0xcc0b, 0x26a2,
837		0xcc0c, 0x3012,
838		0xcc0d, 0x1002,
839		0xcc0e, 0x29c2,
840		0xcc0f, 0x3002,
841		0xcc10, 0x1002,
842		0xcc11, 0x2072,
843		0xcc12, 0x3012,
844		0xcc13, 0x1002,
845		0xcc14, 0x22cd,
846		0xcc15, 0x301d,
847		0xcc16, 0x2e52,
848		0xcc17, 0x3012,
849		0xcc18, 0x1002,
850		0xcc19, 0x28e2,
851		0xcc1a, 0x3002,
852		0xcc1b, 0x1002,
853		0xcc1c, 0x628f,
854		0xcc1d, 0x2ac2,
855		0xcc1e, 0x3012,
856		0xcc1f, 0x1002,
857		0xcc20, 0x5553,
858		0xcc21, 0x2ae2,
859		0xcc22, 0x3002,
860		0xcc23, 0x1302,
861		0xcc24, 0x401e,
862		0xcc25, 0x2be2,
863		0xcc26, 0x3012,
864		0xcc27, 0x1002,
865		0xcc28, 0x2da2,
866		0xcc29, 0x3012,
867		0xcc2a, 0x1002,
868		0xcc2b, 0x2ba2,
869		0xcc2c, 0x3002,
870		0xcc2d, 0x1002,
871		0xcc2e, 0x5ee3,
872		0xcc2f, 0x305,
873		0xcc30, 0x400e,
874		0xcc31, 0x2bc2,
875		0xcc32, 0x3002,
876		0xcc33, 0x1002,
877		0xcc34, 0x2b82,
878		0xcc35, 0x3012,
879		0xcc36, 0x1002,
880		0xcc37, 0x5663,
881		0xcc38, 0x302,
882		0xcc39, 0x401e,
883		0xcc3a, 0x6f72,
884		0xcc3b, 0x1002,
885		0xcc3c, 0x628f,
886		0xcc3d, 0x2be2,
887		0xcc3e, 0x3012,
888		0xcc3f, 0x1002,
889		0xcc40, 0x22cd,
890		0xcc41, 0x301d,
891		0xcc42, 0x2e52,
892		0xcc43, 0x3012,
893		0xcc44, 0x1002,
894		0xcc45, 0x2522,
895		0xcc46, 0x3012,
896		0xcc47, 0x1002,
897		0xcc48, 0x2da2,
898		0xcc49, 0x3012,
899		0xcc4a, 0x1002,
900		0xcc4b, 0x2ca2,
901		0xcc4c, 0x3012,
902		0xcc4d, 0x1002,
903		0xcc4e, 0x2fa4,
904		0xcc4f, 0x3cd4,
905		0xcc50, 0x6624,
906		0xcc51, 0x410b,
907		0xcc52, 0x56b3,
908		0xcc53, 0x3c4,
909		0xcc54, 0x2fb2,
910		0xcc55, 0x3002,
911		0xcc56, 0x1002,
912		0xcc57, 0x220b,
913		0xcc58, 0x303b,
914		0xcc59, 0x56b3,
915		0xcc5a, 0x3c3,
916		0xcc5b, 0x866b,
917		0xcc5c, 0x400c,
918		0xcc5d, 0x23a2,
919		0xcc5e, 0x3012,
920		0xcc5f, 0x1002,
921		0xcc60, 0x2da2,
922		0xcc61, 0x3012,
923		0xcc62, 0x1002,
924		0xcc63, 0x2ca2,
925		0xcc64, 0x3012,
926		0xcc65, 0x1002,
927		0xcc66, 0x2fb4,
928		0xcc67, 0x3cd4,
929		0xcc68, 0x6624,
930		0xcc69, 0x56b3,
931		0xcc6a, 0x3c3,
932		0xcc6b, 0x866b,
933		0xcc6c, 0x401c,
934		0xcc6d, 0x2205,
935		0xcc6e, 0x3035,
936		0xcc6f, 0x5b53,
937		0xcc70, 0x2c52,
938		0xcc71, 0x3002,
939		0xcc72, 0x13c2,
940		0xcc73, 0x5cc3,
941		0xcc74, 0x317,
942		0xcc75, 0x2522,
943		0xcc76, 0x3012,
944		0xcc77, 0x1002,
945		0xcc78, 0x2da2,
946		0xcc79, 0x3012,
947		0xcc7a, 0x1002,
948		0xcc7b, 0x2b82,
949		0xcc7c, 0x3012,
950		0xcc7d, 0x1002,
951		0xcc7e, 0x5663,
952		0xcc7f, 0x303,
953		0xcc80, 0x401e,
954		0xcc81, 0x004,
955		0xcc82, 0x2c42,
956		0xcc83, 0x3012,
957		0xcc84, 0x1002,
958		0xcc85, 0x6f72,
959		0xcc86, 0x1002,
960		0xcc87, 0x628f,
961		0xcc88, 0x2304,
962		0xcc89, 0x3c84,
963		0xcc8a, 0x6436,
964		0xcc8b, 0xdff4,
965		0xcc8c, 0x6436,
966		0xcc8d, 0x2ff5,
967		0xcc8e, 0x3005,
968		0xcc8f, 0x8656,
969		0xcc90, 0xdfba,
970		0xcc91, 0x56a3,
971		0xcc92, 0xd05a,
972		0xcc93, 0x21c2,
973		0xcc94, 0x3012,
974		0xcc95, 0x1392,
975		0xcc96, 0xd05a,
976		0xcc97, 0x56a3,
977		0xcc98, 0xdfba,
978		0xcc99, 0x383,
979		0xcc9a, 0x6f72,
980		0xcc9b, 0x1002,
981		0xcc9c, 0x28c5,
982		0xcc9d, 0x3005,
983		0xcc9e, 0x4178,
984		0xcc9f, 0x5653,
985		0xcca0, 0x384,
986		0xcca1, 0x22b2,
987		0xcca2, 0x3012,
988		0xcca3, 0x1002,
989		0xcca4, 0x2be5,
990		0xcca5, 0x3005,
991		0xcca6, 0x41e8,
992		0xcca7, 0x5653,
993		0xcca8, 0x382,
994		0xcca9, 0x002,
995		0xccaa, 0x4258,
996		0xccab, 0x2474,
997		0xccac, 0x3c84,
998		0xccad, 0x6437,
999		0xccae, 0xdff4,
1000		0xccaf, 0x6437,
1001		0xccb0, 0x2ff5,
1002		0xccb1, 0x3c05,
1003		0xccb2, 0x8757,
1004		0xccb3, 0xb888,
1005		0xccb4, 0x9787,
1006		0xccb5, 0xdff4,
1007		0xccb6, 0x6724,
1008		0xccb7, 0x866a,
1009		0xccb8, 0x6f72,
1010		0xccb9, 0x1002,
1011		0xccba, 0x2d01,
1012		0xccbb, 0x3011,
1013		0xccbc, 0x1001,
1014		0xccbd, 0xc620,
1015		0xccbe, 0x14e5,
1016		0xccbf, 0xc621,
1017		0xccc0, 0xc53d,
1018		0xccc1, 0xc622,
1019		0xccc2, 0x3cbe,
1020		0xccc3, 0xc623,
1021		0xccc4, 0x4452,
1022		0xccc5, 0xc624,
1023		0xccc6, 0xc5c5,
1024		0xccc7, 0xc625,
1025		0xccc8, 0xe01e,
1026		0xccc9, 0xc627,
1027		0xccca, 0x000,
1028		0xcccb, 0xc628,
1029		0xcccc, 0x000,
1030		0xcccd, 0xc62b,
1031		0xccce, 0x000,
1032		0xcccf, 0xc62c,
1033		0xccd0, 0x000,
1034		0xccd1, 0x000,
1035		0xccd2, 0x2d01,
1036		0xccd3, 0x3011,
1037		0xccd4, 0x1001,
1038		0xccd5, 0xc620,
1039		0xccd6, 0x000,
1040		0xccd7, 0xc621,
1041		0xccd8, 0x000,
1042		0xccd9, 0xc622,
1043		0xccda, 0x0ce,
1044		0xccdb, 0xc623,
1045		0xccdc, 0x07f,
1046		0xccdd, 0xc624,
1047		0xccde, 0x032,
1048		0xccdf, 0xc625,
1049		0xcce0, 0x000,
1050		0xcce1, 0xc627,
1051		0xcce2, 0x000,
1052		0xcce3, 0xc628,
1053		0xcce4, 0x000,
1054		0xcce5, 0xc62b,
1055		0xcce6, 0x000,
1056		0xcce7, 0xc62c,
1057		0xcce8, 0x000,
1058		0xcce9, 0x000,
1059		0xccea, 0x2d01,
1060		0xcceb, 0x3011,
1061		0xccec, 0x1001,
1062		0xcced, 0xc502,
1063		0xccee, 0x609f,
1064		0xccef, 0xc600,
1065		0xccf0, 0x2a6e,
1066		0xccf1, 0xc601,
1067		0xccf2, 0x2a2c,
1068		0xccf3, 0xc60c,
1069		0xccf4, 0x5400,
1070		0xccf5, 0xc710,
1071		0xccf6, 0x700,
1072		0xccf7, 0xc718,
1073		0xccf8, 0x700,
1074		0xccf9, 0xc720,
1075		0xccfa, 0x4700,
1076		0xccfb, 0xc728,
1077		0xccfc, 0x700,
1078		0xccfd, 0xc729,
1079		0xccfe, 0x1207,
1080		0xccff, 0xc801,
1081		0xcd00, 0x7f50,
1082		0xcd01, 0xc802,
1083		0xcd02, 0x7760,
1084		0xcd03, 0xc803,
1085		0xcd04, 0x7fce,
1086		0xcd05, 0xc804,
1087		0xcd06, 0x520e,
1088		0xcd07, 0xc805,
1089		0xcd08, 0x5c11,
1090		0xcd09, 0xc806,
1091		0xcd0a, 0x3c51,
1092		0xcd0b, 0xc807,
1093		0xcd0c, 0x4061,
1094		0xcd0d, 0xc808,
1095		0xcd0e, 0x49c1,
1096		0xcd0f, 0xc809,
1097		0xcd10, 0x3840,
1098		0xcd11, 0xc80a,
1099		0xcd12, 0x000,
1100		0xcd13, 0xc821,
1101		0xcd14, 0x002,
1102		0xcd15, 0xc822,
1103		0xcd16, 0x046,
1104		0xcd17, 0xc844,
1105		0xcd18, 0x182f,
1106		0xcd19, 0xc013,
1107		0xcd1a, 0xf341,
1108		0xcd1b, 0xc01a,
1109		0xcd1c, 0x446,
1110		0xcd1d, 0xc024,
1111		0xcd1e, 0x1000,
1112		0xcd1f, 0xc025,
1113		0xcd20, 0xa00,
1114		0xcd21, 0xc026,
1115		0xcd22, 0xc0c,
1116		0xcd23, 0xc027,
1117		0xcd24, 0xc0c,
1118		0xcd25, 0xc029,
1119		0xcd26, 0x0a0,
1120		0xcd27, 0xc030,
1121		0xcd28, 0xa00,
1122		0xcd29, 0xc03c,
1123		0xcd2a, 0x01c,
1124		0xcd2b, 0x000,
1125		0xcd2c, 0x2b84,
1126		0xcd2d, 0x3c74,
1127		0xcd2e, 0x6435,
1128		0xcd2f, 0xdff4,
1129		0xcd30, 0x6435,
1130		0xcd31, 0x2806,
1131		0xcd32, 0x3006,
1132		0xcd33, 0x8565,
1133		0xcd34, 0x2b24,
1134		0xcd35, 0x3c24,
1135		0xcd36, 0x6436,
1136		0xcd37, 0x1002,
1137		0xcd38, 0x2b24,
1138		0xcd39, 0x3c24,
1139		0xcd3a, 0x6436,
1140		0xcd3b, 0x4045,
1141		0xcd3c, 0x8656,
1142		0xcd3d, 0x1002,
1143		0xcd3e, 0x2807,
1144		0xcd3f, 0x31a7,
1145		0xcd40, 0x20c4,
1146		0xcd41, 0x3c24,
1147		0xcd42, 0x6724,
1148		0xcd43, 0x1002,
1149		0xcd44, 0x2807,
1150		0xcd45, 0x3187,
1151		0xcd46, 0x20c4,
1152		0xcd47, 0x3c24,
1153		0xcd48, 0x6724,
1154		0xcd49, 0x1002,
1155		0xcd4a, 0x2514,
1156		0xcd4b, 0x3c64,
1157		0xcd4c, 0x6436,
1158		0xcd4d, 0xdff4,
1159		0xcd4e, 0x6436,
1160		0xcd4f, 0x1002,
1161		0xcd50, 0x2806,
1162		0xcd51, 0x3cb6,
1163		0xcd52, 0xc161,
1164		0xcd53, 0x6134,
1165		0xcd54, 0x6135,
1166		0xcd55, 0x5443,
1167		0xcd56, 0x303,
1168		0xcd57, 0x6524,
1169		0xcd58, 0x00b,
1170		0xcd59, 0x1002,
1171		0xcd5a, 0xd019,
1172		0xcd5b, 0x2104,
1173		0xcd5c, 0x3c24,
1174		0xcd5d, 0x2105,
1175		0xcd5e, 0x3805,
1176		0xcd5f, 0x6524,
1177		0xcd60, 0xdff4,
1178		0xcd61, 0x4005,
1179		0xcd62, 0x6524,
1180		0xcd63, 0x2e8d,
1181		0xcd64, 0x303d,
1182		0xcd65, 0x5dd3,
1183		0xcd66, 0x306,
1184		0xcd67, 0x2ff7,
1185		0xcd68, 0x38f7,
1186		0xcd69, 0x60b7,
1187		0xcd6a, 0xdffd,
1188		0xcd6b, 0x00a,
1189		0xcd6c, 0x1002,
1190		0xcd6d, 0
1191	};
1192	int i, err;
1193
1194	err = set_phy_regs(phy, regs);
1195	if (!err && modtype == phy_modtype_twinax_long)
1196		err = set_phy_regs(phy, preemphasis);
1197	if (err)
1198		return err;
1199
1200	msleep(50);
1201
1202	for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1203		err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1204				 twinax_edc[i + 1]);
1205	if (!err)
1206		phy->priv = edc_twinax;
1207	return err;
1208}
1209
1210static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
1211{
1212	int v;
1213	unsigned int stat;
1214
1215	v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat);
1216	if (v)
1217		return v;
1218
1219	if (stat & (1 << 8))			/* module absent */
1220		return phy_modtype_none;
1221
1222	return ael2xxx_get_module_type(phy, delay_ms);
1223}
1224
1225static int ael2005_intr_enable(struct cphy *phy)
1226{
1227	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200);
1228	return err ? err : t3_phy_lasi_intr_enable(phy);
1229}
1230
1231static int ael2005_intr_disable(struct cphy *phy)
1232{
1233	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100);
1234	return err ? err : t3_phy_lasi_intr_disable(phy);
1235}
1236
1237static int ael2005_intr_clear(struct cphy *phy)
1238{
1239	int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00);
1240	return err ? err : t3_phy_lasi_intr_clear(phy);
1241}
1242
1243static int ael2005_reset(struct cphy *phy, int wait)
1244{
1245	static struct reg_val regs0[] = {
1246		{ MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
1247		{ MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
1248		{ MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
1249		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1250		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
1251		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
1252		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
1253		{ 0, 0, 0, 0 }
1254	};
1255	static struct reg_val regs1[] = {
1256		{ MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
1257		{ MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
1258		{ 0, 0, 0, 0 }
1259	};
1260
1261	int err;
1262	unsigned int lasi_ctrl;
1263
1264	err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
1265	if (err)
1266		return err;
1267
1268	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
1269	if (err)
1270		return err;
1271
1272	msleep(125);
1273	phy->priv = edc_none;
1274	err = set_phy_regs(phy, regs0);
1275	if (err)
1276		return err;
1277
1278	msleep(50);
1279
1280	err = ael2005_get_module_type(phy, 0);
1281	if (err < 0)
1282		return err;
1283	phy->modtype = (u8)err;
1284
1285	if (err == phy_modtype_none)
1286		err = 0;
1287	else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1288		err = ael2005_setup_twinax_edc(phy, err);
1289	else
1290		err = ael2005_setup_sr_edc(phy);
1291	if (err)
1292		return err;
1293
1294	err = set_phy_regs(phy, regs1);
1295	if (err)
1296		return err;
1297
1298	/* reset wipes out interrupts, reenable them if they were on */
1299	if (lasi_ctrl & 1)
1300		err = ael2005_intr_enable(phy);
1301	return err;
1302}
1303
1304static int ael2005_intr_handler(struct cphy *phy)
1305{
1306	unsigned int stat;
1307	int ret, edc_needed, cause = 0;
1308
1309	ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat);
1310	if (ret)
1311		return ret;
1312
1313	if (stat & AEL2005_MODDET_IRQ) {
1314		ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL,
1315				 0xd00);
1316		if (ret)
1317			return ret;
1318
1319		/* modules have max 300 ms init time after hot plug */
1320		ret = ael2005_get_module_type(phy, 300);
1321		if (ret < 0)
1322			return ret;
1323
1324		phy->modtype = (u8)ret;
1325		if (ret == phy_modtype_none)
1326			edc_needed = phy->priv;       /* on unplug retain EDC */
1327		else if (ret == phy_modtype_twinax ||
1328			 ret == phy_modtype_twinax_long)
1329			edc_needed = edc_twinax;
1330		else
1331			edc_needed = edc_sr;
1332
1333		if (edc_needed != phy->priv) {
1334			ret = ael2005_reset(phy, 0);
1335			return ret ? ret : cphy_cause_module_change;
1336		}
1337		cause = cphy_cause_module_change;
1338	}
1339
1340	ret = t3_phy_lasi_intr_handler(phy);
1341	if (ret < 0)
1342		return ret;
1343
1344	ret |= cause;
1345	if (!ret)
1346		ret |= cphy_cause_link_change;
1347	return ret;
1348}
1349
1350static struct cphy_ops ael2005_ops = {
1351#ifdef C99_NOT_SUPPORTED
1352	ael2005_reset,
1353	ael2005_intr_enable,
1354	ael2005_intr_disable,
1355	ael2005_intr_clear,
1356	ael2005_intr_handler,
1357	NULL,
1358	NULL,
1359	NULL,
1360	NULL,
1361	NULL,
1362	get_link_status_r,
1363	ael1002_power_down,
1364#else
1365	.reset           = ael2005_reset,
1366	.intr_enable     = ael2005_intr_enable,
1367	.intr_disable    = ael2005_intr_disable,
1368	.intr_clear      = ael2005_intr_clear,
1369	.intr_handler    = ael2005_intr_handler,
1370	.get_link_status = get_link_status_r,
1371	.power_down      = ael1002_power_down,
1372#endif
1373};
1374
1375int t3_ael2005_phy_prep(pinfo_t *pinfo, int phy_addr,
1376			const struct mdio_ops *mdio_ops)
1377{
1378	int err;
1379	struct cphy *phy = &pinfo->phy;
1380
1381	cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael2005_ops, mdio_ops,
1382		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
1383		  SUPPORTED_IRQ, "10GBASE-R");
1384	msleep(125);
1385	ael_laser_down(phy, 0);
1386
1387	err = ael2005_get_module_type(phy, 0);
1388	if (err >= 0)
1389		phy->modtype = err;
1390
1391	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
1392				   1 << 5);
1393}
1394
1395/*
1396 * Setup EDC and other parameters for operation with an optical module.
1397 */
1398static int ael2020_setup_sr_edc(struct cphy *phy)
1399{
1400	static struct reg_val regs[] = {
1401		{ MDIO_DEV_PMA_PMD, 0xcc01, 0xffff, 0x488a },
1402
1403		{ MDIO_DEV_PMA_PMD, 0xcb1b, 0xffff, 0x0200 },
1404		{ MDIO_DEV_PMA_PMD, 0xcb1c, 0xffff, 0x00f0 },
1405		{ MDIO_DEV_PMA_PMD, 0xcc06, 0xffff, 0x00e0 },
1406
1407		/* end */
1408		{ 0, 0, 0, 0 }
1409	};
1410	int err;
1411
1412	err = set_phy_regs(phy, regs);
1413	msleep(50);
1414	if (err)
1415		return err;
1416
1417	phy->priv = edc_sr;
1418	return 0;
1419}
1420
1421/*
1422 * Setup EDC and other parameters for operation with an TWINAX module.
1423 */
1424static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype)
1425{
1426	static struct reg_val uCclock40MHz[] = {
1427		{ MDIO_DEV_PMA_PMD, 0xff28, 0xffff, 0x4001 },
1428		{ MDIO_DEV_PMA_PMD, 0xff2a, 0xffff, 0x0002 },
1429		{ 0, 0, 0, 0 }
1430	};
1431
1432	static struct reg_val uCclockActivate[] = {
1433		{ MDIO_DEV_PMA_PMD, 0xd000, 0xffff, 0x5200 },
1434		{ 0, 0, 0, 0 }
1435	};
1436
1437	static struct reg_val uCactivate[] = {
1438		{ MDIO_DEV_PMA_PMD, 0xd080, 0xffff, 0x0100 },
1439		{ MDIO_DEV_PMA_PMD, 0xd092, 0xffff, 0x0000 },
1440		{ 0, 0, 0, 0 }
1441	};
1442
1443	static u16 twinax_edc[] = {
1444		0xd800, 0x4009,
1445		0xd801, 0x2fff,
1446		0xd802, 0x300f,
1447		0xd803, 0x40aa,
1448		0xd804, 0x401c,
1449		0xd805, 0x401e,
1450		0xd806, 0x2ff4,
1451		0xd807, 0x3dc4,
1452		0xd808, 0x2035,
1453		0xd809, 0x3035,
1454		0xd80a, 0x6524,
1455		0xd80b, 0x2cb2,
1456		0xd80c, 0x3012,
1457		0xd80d, 0x1002,
1458		0xd80e, 0x26e2,
1459		0xd80f, 0x3022,
1460		0xd810, 0x1002,
1461		0xd811, 0x27d2,
1462		0xd812, 0x3022,
1463		0xd813, 0x1002,
1464		0xd814, 0x2822,
1465		0xd815, 0x3012,
1466		0xd816, 0x1002,
1467		0xd817, 0x2492,
1468		0xd818, 0x3022,
1469		0xd819, 0x1002,
1470		0xd81a, 0x2772,
1471		0xd81b, 0x3012,
1472		0xd81c, 0x1002,
1473		0xd81d, 0x23d2,
1474		0xd81e, 0x3022,
1475		0xd81f, 0x1002,
1476		0xd820, 0x22cd,
1477		0xd821, 0x301d,
1478		0xd822, 0x27f2,
1479		0xd823, 0x3022,
1480		0xd824, 0x1002,
1481		0xd825, 0x5553,
1482		0xd826, 0x0307,
1483		0xd827, 0x2522,
1484		0xd828, 0x3022,
1485		0xd829, 0x1002,
1486		0xd82a, 0x2142,
1487		0xd82b, 0x3012,
1488		0xd82c, 0x1002,
1489		0xd82d, 0x4016,
1490		0xd82e, 0x5e63,
1491		0xd82f, 0x0344,
1492		0xd830, 0x2142,
1493		0xd831, 0x3012,
1494		0xd832, 0x1002,
1495		0xd833, 0x400e,
1496		0xd834, 0x2522,
1497		0xd835, 0x3022,
1498		0xd836, 0x1002,
1499		0xd837, 0x2b52,
1500		0xd838, 0x3012,
1501		0xd839, 0x1002,
1502		0xd83a, 0x2742,
1503		0xd83b, 0x3022,
1504		0xd83c, 0x1002,
1505		0xd83d, 0x25e2,
1506		0xd83e, 0x3022,
1507		0xd83f, 0x1002,
1508		0xd840, 0x2fa4,
1509		0xd841, 0x3dc4,
1510		0xd842, 0x6624,
1511		0xd843, 0x414b,
1512		0xd844, 0x56b3,
1513		0xd845, 0x03c6,
1514		0xd846, 0x866b,
1515		0xd847, 0x400c,
1516		0xd848, 0x2712,
1517		0xd849, 0x3012,
1518		0xd84a, 0x1002,
1519		0xd84b, 0x2c4b,
1520		0xd84c, 0x309b,
1521		0xd84d, 0x56b3,
1522		0xd84e, 0x03c3,
1523		0xd84f, 0x866b,
1524		0xd850, 0x400c,
1525		0xd851, 0x2272,
1526		0xd852, 0x3022,
1527		0xd853, 0x1002,
1528		0xd854, 0x2742,
1529		0xd855, 0x3022,
1530		0xd856, 0x1002,
1531		0xd857, 0x25e2,
1532		0xd858, 0x3022,
1533		0xd859, 0x1002,
1534		0xd85a, 0x2fb4,
1535		0xd85b, 0x3dc4,
1536		0xd85c, 0x6624,
1537		0xd85d, 0x56b3,
1538		0xd85e, 0x03c3,
1539		0xd85f, 0x866b,
1540		0xd860, 0x401c,
1541		0xd861, 0x2c45,
1542		0xd862, 0x3095,
1543		0xd863, 0x5b53,
1544		0xd864, 0x2372,
1545		0xd865, 0x3012,
1546		0xd866, 0x13c2,
1547		0xd867, 0x5cc3,
1548		0xd868, 0x2712,
1549		0xd869, 0x3012,
1550		0xd86a, 0x1312,
1551		0xd86b, 0x2b52,
1552		0xd86c, 0x3012,
1553		0xd86d, 0x1002,
1554		0xd86e, 0x2742,
1555		0xd86f, 0x3022,
1556		0xd870, 0x1002,
1557		0xd871, 0x2582,
1558		0xd872, 0x3022,
1559		0xd873, 0x1002,
1560		0xd874, 0x2142,
1561		0xd875, 0x3012,
1562		0xd876, 0x1002,
1563		0xd877, 0x628f,
1564		0xd878, 0x2985,
1565		0xd879, 0x33a5,
1566		0xd87a, 0x25e2,
1567		0xd87b, 0x3022,
1568		0xd87c, 0x1002,
1569		0xd87d, 0x5653,
1570		0xd87e, 0x03d2,
1571		0xd87f, 0x401e,
1572		0xd880, 0x6f72,
1573		0xd881, 0x1002,
1574		0xd882, 0x628f,
1575		0xd883, 0x2304,
1576		0xd884, 0x3c84,
1577		0xd885, 0x6436,
1578		0xd886, 0xdff4,
1579		0xd887, 0x6436,
1580		0xd888, 0x2ff5,
1581		0xd889, 0x3005,
1582		0xd88a, 0x8656,
1583		0xd88b, 0xdfba,
1584		0xd88c, 0x56a3,
1585		0xd88d, 0xd05a,
1586		0xd88e, 0x2972,
1587		0xd88f, 0x3012,
1588		0xd890, 0x1392,
1589		0xd891, 0xd05a,
1590		0xd892, 0x56a3,
1591		0xd893, 0xdfba,
1592		0xd894, 0x0383,
1593		0xd895, 0x6f72,
1594		0xd896, 0x1002,
1595		0xd897, 0x2b45,
1596		0xd898, 0x3005,
1597		0xd899, 0x4178,
1598		0xd89a, 0x5653,
1599		0xd89b, 0x0384,
1600		0xd89c, 0x2a62,
1601		0xd89d, 0x3012,
1602		0xd89e, 0x1002,
1603		0xd89f, 0x2f05,
1604		0xd8a0, 0x3005,
1605		0xd8a1, 0x41c8,
1606		0xd8a2, 0x5653,
1607		0xd8a3, 0x0382,
1608		0xd8a4, 0x0002,
1609		0xd8a5, 0x4218,
1610		0xd8a6, 0x2474,
1611		0xd8a7, 0x3c84,
1612		0xd8a8, 0x6437,
1613		0xd8a9, 0xdff4,
1614		0xd8aa, 0x6437,
1615		0xd8ab, 0x2ff5,
1616		0xd8ac, 0x3c05,
1617		0xd8ad, 0x8757,
1618		0xd8ae, 0xb888,
1619		0xd8af, 0x9787,
1620		0xd8b0, 0xdff4,
1621		0xd8b1, 0x6724,
1622		0xd8b2, 0x866a,
1623		0xd8b3, 0x6f72,
1624		0xd8b4, 0x1002,
1625		0xd8b5, 0x2641,
1626		0xd8b6, 0x3021,
1627		0xd8b7, 0x1001,
1628		0xd8b8, 0xc620,
1629		0xd8b9, 0x0000,
1630		0xd8ba, 0xc621,
1631		0xd8bb, 0x0000,
1632		0xd8bc, 0xc622,
1633		0xd8bd, 0x00ce,
1634		0xd8be, 0xc623,
1635		0xd8bf, 0x007f,
1636		0xd8c0, 0xc624,
1637		0xd8c1, 0x0032,
1638		0xd8c2, 0xc625,
1639		0xd8c3, 0x0000,
1640		0xd8c4, 0xc627,
1641		0xd8c5, 0x0000,
1642		0xd8c6, 0xc628,
1643		0xd8c7, 0x0000,
1644		0xd8c8, 0xc62c,
1645		0xd8c9, 0x0000,
1646		0xd8ca, 0x0000,
1647		0xd8cb, 0x2641,
1648		0xd8cc, 0x3021,
1649		0xd8cd, 0x1001,
1650		0xd8ce, 0xc502,
1651		0xd8cf, 0x53ac,
1652		0xd8d0, 0xc503,
1653		0xd8d1, 0x2cd3,
1654		0xd8d2, 0xc600,
1655		0xd8d3, 0x2a6e,
1656		0xd8d4, 0xc601,
1657		0xd8d5, 0x2a2c,
1658		0xd8d6, 0xc605,
1659		0xd8d7, 0x5557,
1660		0xd8d8, 0xc60c,
1661		0xd8d9, 0x5400,
1662		0xd8da, 0xc710,
1663		0xd8db, 0x0700,
1664		0xd8dc, 0xc711,
1665		0xd8dd, 0x0f06,
1666		0xd8de, 0xc718,
1667		0xd8df, 0x0700,
1668		0xd8e0, 0xc719,
1669		0xd8e1, 0x0f06,
1670		0xd8e2, 0xc720,
1671		0xd8e3, 0x4700,
1672		0xd8e4, 0xc721,
1673		0xd8e5, 0x0f06,
1674		0xd8e6, 0xc728,
1675		0xd8e7, 0x0700,
1676		0xd8e8, 0xc729,
1677		0xd8e9, 0x1207,
1678		0xd8ea, 0xc801,
1679		0xd8eb, 0x7f50,
1680		0xd8ec, 0xc802,
1681		0xd8ed, 0x7760,
1682		0xd8ee, 0xc803,
1683		0xd8ef, 0x7fce,
1684		0xd8f0, 0xc804,
1685		0xd8f1, 0x520e,
1686		0xd8f2, 0xc805,
1687		0xd8f3, 0x5c11,
1688		0xd8f4, 0xc806,
1689		0xd8f5, 0x3c51,
1690		0xd8f6, 0xc807,
1691		0xd8f7, 0x4061,
1692		0xd8f8, 0xc808,
1693		0xd8f9, 0x49c1,
1694		0xd8fa, 0xc809,
1695		0xd8fb, 0x3840,
1696		0xd8fc, 0xc80a,
1697		0xd8fd, 0x0000,
1698		0xd8fe, 0xc821,
1699		0xd8ff, 0x0002,
1700		0xd900, 0xc822,
1701		0xd901, 0x0046,
1702		0xd902, 0xc844,
1703		0xd903, 0x182f,
1704		0xd904, 0xc013,
1705		0xd905, 0xf341,
1706		0xd906, 0xc084,
1707		0xd907, 0x0030,
1708		0xd908, 0xc904,
1709		0xd909, 0x1401,
1710		0xd90a, 0xcb0c,
1711		0xd90b, 0x0004,
1712		0xd90c, 0xcb0e,
1713		0xd90d, 0xa00a,
1714		0xd90e, 0xcb0f,
1715		0xd90f, 0xc0c0,
1716		0xd910, 0xcb10,
1717		0xd911, 0xc0c0,
1718		0xd912, 0xcb11,
1719		0xd913, 0x00a0,
1720		0xd914, 0xcb12,
1721		0xd915, 0x0007,
1722		0xd916, 0xc241,
1723		0xd917, 0xa000,
1724		0xd918, 0xc243,
1725		0xd919, 0x7fe0,
1726		0xd91a, 0xc604,
1727		0xd91b, 0x000e,
1728		0xd91c, 0xc609,
1729		0xd91d, 0x00f5,
1730		0xd91e, 0xc611,
1731		0xd91f, 0x000e,
1732		0xd920, 0xc660,
1733		0xd921, 0x9600,
1734		0xd922, 0xc687,
1735		0xd923, 0x0004,
1736		0xd924, 0xc60a,
1737		0xd925, 0x04f5,
1738		0xd926, 0x0000,
1739		0xd927, 0x2641,
1740		0xd928, 0x3021,
1741		0xd929, 0x1001,
1742		0xd92a, 0xc620,
1743		0xd92b, 0x14e5,
1744		0xd92c, 0xc621,
1745		0xd92d, 0xc53d,
1746		0xd92e, 0xc622,
1747		0xd92f, 0x3cbe,
1748		0xd930, 0xc623,
1749		0xd931, 0x4452,
1750		0xd932, 0xc624,
1751		0xd933, 0xc5c5,
1752		0xd934, 0xc625,
1753		0xd935, 0xe01e,
1754		0xd936, 0xc627,
1755		0xd937, 0x0000,
1756		0xd938, 0xc628,
1757		0xd939, 0x0000,
1758		0xd93a, 0xc62c,
1759		0xd93b, 0x0000,
1760		0xd93c, 0x0000,
1761		0xd93d, 0x2b84,
1762		0xd93e, 0x3c74,
1763		0xd93f, 0x6435,
1764		0xd940, 0xdff4,
1765		0xd941, 0x6435,
1766		0xd942, 0x2806,
1767		0xd943, 0x3006,
1768		0xd944, 0x8565,
1769		0xd945, 0x2b24,
1770		0xd946, 0x3c24,
1771		0xd947, 0x6436,
1772		0xd948, 0x1002,
1773		0xd949, 0x2b24,
1774		0xd94a, 0x3c24,
1775		0xd94b, 0x6436,
1776		0xd94c, 0x4045,
1777		0xd94d, 0x8656,
1778		0xd94e, 0x5663,
1779		0xd94f, 0x0302,
1780		0xd950, 0x401e,
1781		0xd951, 0x1002,
1782		0xd952, 0x2807,
1783		0xd953, 0x31a7,
1784		0xd954, 0x20c4,
1785		0xd955, 0x3c24,
1786		0xd956, 0x6724,
1787		0xd957, 0x1002,
1788		0xd958, 0x2807,
1789		0xd959, 0x3187,
1790		0xd95a, 0x20c4,
1791		0xd95b, 0x3c24,
1792		0xd95c, 0x6724,
1793		0xd95d, 0x1002,
1794		0xd95e, 0x24f4,
1795		0xd95f, 0x3c64,
1796		0xd960, 0x6436,
1797		0xd961, 0xdff4,
1798		0xd962, 0x6436,
1799		0xd963, 0x1002,
1800		0xd964, 0x2006,
1801		0xd965, 0x3d76,
1802		0xd966, 0xc161,
1803		0xd967, 0x6134,
1804		0xd968, 0x6135,
1805		0xd969, 0x5443,
1806		0xd96a, 0x0303,
1807		0xd96b, 0x6524,
1808		0xd96c, 0x00fb,
1809		0xd96d, 0x1002,
1810		0xd96e, 0x20d4,
1811		0xd96f, 0x3c24,
1812		0xd970, 0x2025,
1813		0xd971, 0x3005,
1814		0xd972, 0x6524,
1815		0xd973, 0x1002,
1816		0xd974, 0xd019,
1817		0xd975, 0x2104,
1818		0xd976, 0x3c24,
1819		0xd977, 0x2105,
1820		0xd978, 0x3805,
1821		0xd979, 0x6524,
1822		0xd97a, 0xdff4,
1823		0xd97b, 0x4005,
1824		0xd97c, 0x6524,
1825		0xd97d, 0x2e8d,
1826		0xd97e, 0x303d,
1827		0xd97f, 0x2408,
1828		0xd980, 0x35d8,
1829		0xd981, 0x5dd3,
1830		0xd982, 0x0307,
1831		0xd983, 0x8887,
1832		0xd984, 0x63a7,
1833		0xd985, 0x8887,
1834		0xd986, 0x63a7,
1835		0xd987, 0xdffd,
1836		0xd988, 0x00f9,
1837		0xd989, 0x1002,
1838		0xd98a, 0x0000,
1839	};
1840	int i, err;
1841
1842	/* set uC clock and activate it */
1843	err = set_phy_regs(phy, uCclock40MHz);
1844	msleep(500);
1845	if (err)
1846		return err;
1847	err = set_phy_regs(phy, uCclockActivate);
1848	msleep(500);
1849	if (err)
1850		return err;
1851
1852	for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2)
1853		err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i],
1854				 twinax_edc[i + 1]);
1855	/* activate uC */
1856	err = set_phy_regs(phy, uCactivate);
1857	if (!err)
1858		phy->priv = edc_twinax;
1859	return err;
1860}
1861
1862/*
1863 * Return Module Type.
1864 */
1865static int ael2020_get_module_type(struct cphy *phy, int delay_ms)
1866{
1867	int v;
1868	unsigned int stat;
1869
1870	v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_STAT, &stat);
1871	if (v)
1872		return v;
1873
1874	if (stat & (0x1 << (AEL2020_GPIO_MODDET*4))) {
1875		/* module absent */
1876		return phy_modtype_none;
1877	}
1878
1879	return ael2xxx_get_module_type(phy, delay_ms);
1880}
1881
1882/*
1883 * Enable PHY interrupts.  We enable "Module Detection" interrupts (on any
1884 * state transition) and then generic Link Alarm Status Interrupt (LASI).
1885 */
1886static int ael2020_intr_enable(struct cphy *phy)
1887{
1888	struct reg_val regs[] = {
1889		{ MDIO_DEV_PMA_PMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT,
1890			0xffff, 0x4 },
1891		{ MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1892			0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) },
1893
1894		{ MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1895			0xffff, 0x2 << (AEL2020_GPIO_MODDET*4) },
1896
1897		/* end */
1898		{ 0, 0, 0, 0 }
1899	};
1900	int err;
1901
1902	err = set_phy_regs(phy, regs);
1903	if (err)
1904		return err;
1905
1906	phy->caps |= POLL_LINK_1ST_TIME;
1907
1908	/* enable standard Link Alarm Status Interrupts */
1909	err = t3_phy_lasi_intr_enable(phy);
1910	if (err)
1911		return err;
1912
1913	return 0;
1914}
1915
1916/*
1917 * Disable PHY interrupts.  The mirror of the above ...
1918 */
1919static int ael2020_intr_disable(struct cphy *phy)
1920{
1921	struct reg_val regs[] = {
1922		{ MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1923			0xffff, 0xb << (AEL2020_GPIO_LSTAT*4) },
1924
1925		{ MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL,
1926			0xffff, 0x1 << (AEL2020_GPIO_MODDET*4) },
1927
1928		/* end */
1929		{ 0, 0, 0, 0 }
1930	};
1931	int err;
1932
1933	err = set_phy_regs(phy, regs);
1934	if (err)
1935		return err;
1936
1937	/* disable standard Link Alarm Status Interrupts */
1938	return t3_phy_lasi_intr_disable(phy);
1939}
1940
1941/*
1942 * Clear PHY interrupt state.
1943 */
1944static int ael2020_intr_clear(struct cphy *phy)
1945{
1946	unsigned int stat;
1947	int err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_INTR, &stat);
1948	return err ? err : t3_phy_lasi_intr_clear(phy);
1949}
1950
1951/*
1952 * Common register settings for the AEL2020 when it comes out of reset.
1953 */
1954static struct reg_val ael2020_reset_regs[] = {
1955	{ MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x3101 },
1956
1957	{ MDIO_DEV_PMA_PMD, 0xcd40, 0xffff, 0x0001 },
1958
1959	{ MDIO_DEV_PMA_PMD, 0xff02, 0xffff, 0x0023 },
1960	{ MDIO_DEV_PMA_PMD, 0xff03, 0xffff, 0x0000 },
1961	{ MDIO_DEV_PMA_PMD, 0xff04, 0xffff, 0x0000 },
1962
1963	/* end */
1964	{ 0, 0, 0, 0 }
1965};
1966
1967/*
1968 * Reset the PHY and put it into a canonical operating state.
1969 */
1970static int ael2020_reset(struct cphy *phy, int wait)
1971{
1972	int err;
1973	unsigned int lasi_ctrl;
1974
1975	/* grab current interrupt state */
1976	err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl);
1977	if (err)
1978		return err;
1979
1980	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 125);
1981	if (err)
1982		return err;
1983	msleep(100);
1984
1985	/* basic initialization for all module types */
1986	phy->priv = edc_none;
1987	err = set_phy_regs(phy, ael2020_reset_regs);
1988	if (err)
1989		return err;
1990
1991	/* determine module type and perform appropriate initialization */
1992	err = ael2020_get_module_type(phy, 0);
1993	if (err < 0)
1994		return err;
1995	phy->modtype = (u8)err;
1996	if (err == phy_modtype_none)
1997		err = 0;
1998	else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long)
1999		err = ael2020_setup_twinax_edc(phy, err);
2000	else
2001		err = ael2020_setup_sr_edc(phy);
2002	if (err)
2003		return err;
2004
2005	/* reset wipes out interrupts, reenable them if they were on */
2006	if (lasi_ctrl & 1)
2007		err = ael2020_intr_enable(phy);
2008	return err;
2009}
2010
2011/*
2012 * Handle a PHY interrupt.
2013 */
2014static int ael2020_intr_handler(struct cphy *phy)
2015{
2016	unsigned int stat;
2017	int ret, edc_needed, cause = 0;
2018
2019	ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_INTR, &stat);
2020	if (ret)
2021		return ret;
2022
2023	if (stat & (0x1 << AEL2020_GPIO_MODDET)) {
2024		/* modules have max 300 ms init time after hot plug */
2025		ret = ael2020_get_module_type(phy, 300);
2026		if (ret < 0)
2027			return ret;
2028
2029		phy->modtype = (u8)ret;
2030		if (ret == phy_modtype_none)
2031			edc_needed = phy->priv;       /* on unplug retain EDC */
2032		else if (ret == phy_modtype_twinax ||
2033			 ret == phy_modtype_twinax_long)
2034			edc_needed = edc_twinax;
2035		else
2036			edc_needed = edc_sr;
2037
2038		if (edc_needed != phy->priv) {
2039			ret = ael2020_reset(phy, 0);
2040			return ret ? ret : cphy_cause_module_change;
2041		}
2042		cause = cphy_cause_module_change;
2043	}
2044
2045	ret = t3_phy_lasi_intr_handler(phy);
2046	if (ret < 0)
2047		return ret;
2048
2049	ret |= cause;
2050	if (!ret)
2051		ret |= cphy_cause_link_change;
2052	return ret;
2053}
2054
2055static struct cphy_ops ael2020_ops = {
2056#ifdef C99_NOT_SUPPORTED
2057	ael2020_reset,
2058	ael2020_intr_enable,
2059	ael2020_intr_disable,
2060	ael2020_intr_clear,
2061	ael2020_intr_handler,
2062	NULL,
2063	NULL,
2064	NULL,
2065	NULL,
2066	NULL,
2067	get_link_status_r,
2068	ael1002_power_down,
2069#else
2070	.reset           = ael2020_reset,
2071	.intr_enable     = ael2020_intr_enable,
2072	.intr_disable    = ael2020_intr_disable,
2073	.intr_clear      = ael2020_intr_clear,
2074	.intr_handler    = ael2020_intr_handler,
2075	.get_link_status = get_link_status_r,
2076	.power_down      = ael1002_power_down,
2077#endif
2078};
2079
2080int t3_ael2020_phy_prep(pinfo_t *pinfo, int phy_addr,
2081			const struct mdio_ops *mdio_ops)
2082{
2083	int err;
2084	struct cphy *phy = &pinfo->phy;
2085
2086	cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael2020_ops, mdio_ops,
2087		SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
2088		  SUPPORTED_IRQ, "10GBASE-R");
2089	msleep(125);
2090
2091	err = set_phy_regs(phy, ael2020_reset_regs);
2092	if (err)
2093		return err;
2094	err = ael2020_get_module_type(phy, 0);
2095	if (err >= 0)
2096		phy->modtype = err;
2097
2098	ael_laser_down(phy, 0);
2099	return 0;
2100}
2101
2102/*
2103 * Get link status for a 10GBASE-X device.
2104 */
2105static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed,
2106			     int *duplex, int *fc)
2107{
2108	if (link_ok) {
2109		unsigned int stat0, stat1, stat2;
2110		int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0);
2111
2112		if (!err)
2113			err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1);
2114		if (!err)
2115			err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2);
2116		if (err)
2117			return err;
2118		*link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1;
2119	}
2120	if (speed)
2121		*speed = SPEED_10000;
2122	if (duplex)
2123		*duplex = DUPLEX_FULL;
2124	return 0;
2125}
2126
2127#ifdef C99_NOT_SUPPORTED
2128static struct cphy_ops qt2045_ops = {
2129	ael1006_reset,
2130	t3_phy_lasi_intr_enable,
2131	t3_phy_lasi_intr_disable,
2132	t3_phy_lasi_intr_clear,
2133	t3_phy_lasi_intr_handler,
2134	NULL,
2135	NULL,
2136	NULL,
2137	NULL,
2138	NULL,
2139	get_link_status_x,
2140	ael1002_power_down,
2141};
2142#else
2143static struct cphy_ops qt2045_ops = {
2144	.reset           = ael1006_reset,
2145	.intr_enable     = t3_phy_lasi_intr_enable,
2146	.intr_disable    = t3_phy_lasi_intr_disable,
2147	.intr_clear      = t3_phy_lasi_intr_clear,
2148	.intr_handler    = t3_phy_lasi_intr_handler,
2149	.get_link_status = get_link_status_x,
2150	.power_down      = ael1002_power_down,
2151};
2152#endif
2153
2154int t3_qt2045_phy_prep(pinfo_t *pinfo, int phy_addr,
2155		       const struct mdio_ops *mdio_ops)
2156{
2157	unsigned int stat;
2158	struct cphy *phy = &pinfo->phy;
2159
2160	cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &qt2045_ops, mdio_ops,
2161		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
2162		  "10GBASE-CX4");
2163
2164	/*
2165	 * Some cards where the PHY is supposed to be at address 0 actually
2166	 * have it at 1.
2167	 */
2168	if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
2169	    stat == 0xffff)
2170		phy->addr = 1;
2171	return 0;
2172}
2173
2174static int xaui_direct_reset(struct cphy *phy, int wait)
2175{
2176	return 0;
2177}
2178
2179static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
2180				       int *speed, int *duplex, int *fc)
2181{
2182	if (link_ok) {
2183		unsigned int status;
2184		adapter_t *adapter = phy->adapter;
2185
2186		status = t3_read_reg(adapter,
2187				     XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
2188			 t3_read_reg(adapter,
2189				     XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
2190			 t3_read_reg(adapter,
2191				     XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
2192			 t3_read_reg(adapter,
2193				     XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
2194		*link_ok = !(status & F_LOWSIG0);
2195	}
2196	if (speed)
2197		*speed = SPEED_10000;
2198	if (duplex)
2199		*duplex = DUPLEX_FULL;
2200	return 0;
2201}
2202
2203static int xaui_direct_power_down(struct cphy *phy, int enable)
2204{
2205	return 0;
2206}
2207
2208#ifdef C99_NOT_SUPPORTED
2209static struct cphy_ops xaui_direct_ops = {
2210	xaui_direct_reset,
2211	ael1002_intr_noop,
2212	ael1002_intr_noop,
2213	ael1002_intr_noop,
2214	ael1002_intr_noop,
2215	NULL,
2216	NULL,
2217	NULL,
2218	NULL,
2219	NULL,
2220	xaui_direct_get_link_status,
2221	xaui_direct_power_down,
2222};
2223#else
2224static struct cphy_ops xaui_direct_ops = {
2225	.reset           = xaui_direct_reset,
2226	.intr_enable     = ael1002_intr_noop,
2227	.intr_disable    = ael1002_intr_noop,
2228	.intr_clear      = ael1002_intr_noop,
2229	.intr_handler    = ael1002_intr_noop,
2230	.get_link_status = xaui_direct_get_link_status,
2231	.power_down      = xaui_direct_power_down,
2232};
2233#endif
2234
2235int t3_xaui_direct_phy_prep(pinfo_t *pinfo, int phy_addr,
2236			    const struct mdio_ops *mdio_ops)
2237{
2238	cphy_init(&pinfo->phy, pinfo->adapter, pinfo, phy_addr, &xaui_direct_ops, mdio_ops,
2239		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
2240		  "10GBASE-CX4");
2241	return 0;
2242}
2243