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