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