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