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