cxgb_ael1002.c revision 180583
1/**************************************************************************
2
3Copyright (c) 2007-2008, Chelsio Inc.
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are met:
8
9 1. Redistributions of source code must retain the above copyright notice,
10    this list of conditions and the following disclaimer.
11
12 2. Neither the name of the Chelsio Corporation nor the names of its
13    contributors may be used to endorse or promote products derived from
14    this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26POSSIBILITY OF SUCH DAMAGE.
27
28***************************************************************************/
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/dev/cxgb/common/cxgb_ael1002.c 180583 2008-07-18 06:12:31Z kmacy $");
32
33#ifdef CONFIG_DEFINED
34#include <cxgb_include.h>
35#else
36#include <dev/cxgb/cxgb_include.h>
37#endif
38
39#undef msleep
40#define msleep t3_os_sleep
41
42enum {
43	AEL100X_TX_DISABLE  = 9,
44	AEL100X_TX_CONFIG1  = 0xc002,
45	AEL1002_PWR_DOWN_HI = 0xc011,
46	AEL1002_PWR_DOWN_LO = 0xc012,
47	AEL1002_XFI_EQL     = 0xc015,
48	AEL1002_LB_EN       = 0xc017,
49	AEL_OPT_SETTINGS    = 0xc017,
50};
51
52struct reg_val {
53	unsigned short mmd_addr;
54	unsigned short reg_addr;
55	unsigned short clear_bits;
56	unsigned short set_bits;
57};
58
59static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
60{
61	int err;
62
63	for (err = 0; rv->mmd_addr && !err; rv++) {
64		if (rv->clear_bits == 0xffff)
65			err = mdio_write(phy, rv->mmd_addr, rv->reg_addr,
66					 rv->set_bits);
67		else
68			err = t3_mdio_change_bits(phy, rv->mmd_addr,
69						  rv->reg_addr, rv->clear_bits,
70						  rv->set_bits);
71	}
72	return err;
73}
74
75static void ael100x_txon(struct cphy *phy)
76{
77	int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL;
78
79	msleep(100);
80	t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio);
81	msleep(30);
82}
83
84static int ael1002_power_down(struct cphy *phy, int enable)
85{
86	int err;
87
88	err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable);
89	if (!err)
90		err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
91					  BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
92	return err;
93}
94
95static int ael1002_reset(struct cphy *phy, int wait)
96{
97	int err;
98
99	if ((err = ael1002_power_down(phy, 0)) ||
100	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) ||
101	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) ||
102	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) ||
103	    (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) ||
104	    (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
105				       0, 1 << 5)))
106		return err;
107	return 0;
108}
109
110static int ael1002_intr_noop(struct cphy *phy)
111{
112	return 0;
113}
114
115static int ael100x_get_link_status(struct cphy *phy, int *link_ok,
116				   int *speed, int *duplex, int *fc)
117{
118	if (link_ok) {
119		unsigned int status;
120		int err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &status);
121
122		/*
123		 * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
124		 * once more to get the current link state.
125		 */
126		if (!err && !(status & BMSR_LSTATUS))
127			err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR,
128					&status);
129		if (err)
130			return err;
131		*link_ok = !!(status & BMSR_LSTATUS);
132	}
133	if (speed)
134		*speed = SPEED_10000;
135	if (duplex)
136		*duplex = DUPLEX_FULL;
137	return 0;
138}
139
140#ifdef C99_NOT_SUPPORTED
141static struct cphy_ops ael1002_ops = {
142	ael1002_reset,
143	ael1002_intr_noop,
144	ael1002_intr_noop,
145	ael1002_intr_noop,
146	ael1002_intr_noop,
147	NULL,
148	NULL,
149	NULL,
150	NULL,
151	NULL,
152	ael100x_get_link_status,
153	ael1002_power_down,
154};
155#else
156static struct cphy_ops ael1002_ops = {
157	.reset           = ael1002_reset,
158	.intr_enable     = ael1002_intr_noop,
159	.intr_disable    = ael1002_intr_noop,
160	.intr_clear      = ael1002_intr_noop,
161	.intr_handler    = ael1002_intr_noop,
162	.get_link_status = ael100x_get_link_status,
163	.power_down      = ael1002_power_down,
164};
165#endif
166
167int t3_ael1002_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
168			const struct mdio_ops *mdio_ops)
169{
170	cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops,
171		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
172		  "10GBASE-R");
173	ael100x_txon(phy);
174	return 0;
175}
176
177static int ael1006_reset(struct cphy *phy, int wait)
178{
179	return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
180}
181
182static int ael1006_power_down(struct cphy *phy, int enable)
183{
184	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
185				   BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
186}
187
188#ifdef C99_NOT_SUPPORTED
189static struct cphy_ops ael1006_ops = {
190	ael1006_reset,
191	t3_phy_lasi_intr_enable,
192	t3_phy_lasi_intr_disable,
193	t3_phy_lasi_intr_clear,
194	t3_phy_lasi_intr_handler,
195	NULL,
196	NULL,
197	NULL,
198	NULL,
199	NULL,
200	ael100x_get_link_status,
201	ael1006_power_down,
202};
203#else
204static struct cphy_ops ael1006_ops = {
205	.reset           = ael1006_reset,
206	.intr_enable     = t3_phy_lasi_intr_enable,
207	.intr_disable    = t3_phy_lasi_intr_disable,
208	.intr_clear      = t3_phy_lasi_intr_clear,
209	.intr_handler    = t3_phy_lasi_intr_handler,
210	.get_link_status = ael100x_get_link_status,
211	.power_down      = ael1006_power_down,
212};
213#endif
214
215int t3_ael1006_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
216			const struct mdio_ops *mdio_ops)
217{
218	cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops,
219		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
220		  "10GBASE-SR");
221	ael100x_txon(phy);
222	return 0;
223}
224
225static int ael2005_setup_sr_edc(struct cphy *phy)
226{
227	static u16 sr_edc[] = {
228		0xcc00, 0x2ff4,
229		0xcc01, 0x3cd4,
230		0xcc02, 0x2015,
231		0xcc03, 0x3105,
232		0xcc04, 0x6524,
233		0xcc05, 0x27ff,
234		0xcc06, 0x300f,
235		0xcc07, 0x2c8b,
236		0xcc08, 0x300b,
237		0xcc09, 0x4009,
238		0xcc0a, 0x400e,
239		0xcc0b, 0x2f72,
240		0xcc0c, 0x3002,
241		0xcc0d, 0x1002,
242		0xcc0e, 0x2172,
243		0xcc0f, 0x3012,
244		0xcc10, 0x1002,
245		0xcc11, 0x25d2,
246		0xcc12, 0x3012,
247		0xcc13, 0x1002,
248		0xcc14, 0xd01e,
249		0xcc15, 0x27d2,
250		0xcc16, 0x3012,
251		0xcc17, 0x1002,
252		0xcc18, 0x2004,
253		0xcc19, 0x3c84,
254		0xcc1a, 0x6436,
255		0xcc1b, 0x2007,
256		0xcc1c, 0x3f87,
257		0xcc1d, 0x8676,
258		0xcc1e, 0x40b7,
259		0xcc1f, 0xa746,
260		0xcc20, 0x4047,
261		0xcc21, 0x5673,
262		0xcc22, 0x2982,
263		0xcc23, 0x3002,
264		0xcc24, 0x13d2,
265		0xcc25, 0x8bbd,
266		0xcc26, 0x2862,
267		0xcc27, 0x3012,
268		0xcc28, 0x1002,
269		0xcc29, 0x2092,
270		0xcc2a, 0x3012,
271		0xcc2b, 0x1002,
272		0xcc2c, 0x5cc3,
273		0xcc2d, 0x314,
274		0xcc2e, 0x2942,
275		0xcc2f, 0x3002,
276		0xcc30, 0x1002,
277		0xcc31, 0xd019,
278		0xcc32, 0x2032,
279		0xcc33, 0x3012,
280		0xcc34, 0x1002,
281		0xcc35, 0x2a04,
282		0xcc36, 0x3c74,
283		0xcc37, 0x6435,
284		0xcc38, 0x2fa4,
285		0xcc39, 0x3cd4,
286		0xcc3a, 0x6624,
287		0xcc3b, 0x5563,
288		0xcc3c, 0x2d42,
289		0xcc3d, 0x3002,
290		0xcc3e, 0x13d2,
291		0xcc3f, 0x464d,
292		0xcc40, 0x2862,
293		0xcc41, 0x3012,
294		0xcc42, 0x1002,
295		0xcc43, 0x2032,
296		0xcc44, 0x3012,
297		0xcc45, 0x1002,
298		0xcc46, 0x2fb4,
299		0xcc47, 0x3cd4,
300		0xcc48, 0x6624,
301		0xcc49, 0x5563,
302		0xcc4a, 0x2d42,
303		0xcc4b, 0x3002,
304		0xcc4c, 0x13d2,
305		0xcc4d, 0x2ed2,
306		0xcc4e, 0x3002,
307		0xcc4f, 0x1002,
308		0xcc50, 0x2fd2,
309		0xcc51, 0x3002,
310		0xcc52, 0x1002,
311		0xcc53, 0x004,
312		0xcc54, 0x2942,
313		0xcc55, 0x3002,
314		0xcc56, 0x1002,
315		0xcc57, 0x2092,
316		0xcc58, 0x3012,
317		0xcc59, 0x1002,
318		0xcc5a, 0x5cc3,
319		0xcc5b, 0x317,
320		0xcc5c, 0x2f72,
321		0xcc5d, 0x3002,
322		0xcc5e, 0x1002,
323		0xcc5f, 0x2942,
324		0xcc60, 0x3002,
325		0xcc61, 0x1002,
326		0xcc62, 0x22cd,
327		0xcc63, 0x301d,
328		0xcc64, 0x2862,
329		0xcc65, 0x3012,
330		0xcc66, 0x1002,
331		0xcc67, 0x2ed2,
332		0xcc68, 0x3002,
333		0xcc69, 0x1002,
334		0xcc6a, 0x2d72,
335		0xcc6b, 0x3002,
336		0xcc6c, 0x1002,
337		0xcc6d, 0x628f,
338		0xcc6e, 0x2112,
339		0xcc6f, 0x3012,
340		0xcc70, 0x1002,
341		0xcc71, 0x5aa3,
342		0xcc72, 0x2dc2,
343		0xcc73, 0x3002,
344		0xcc74, 0x1312,
345		0xcc75, 0x6f72,
346		0xcc76, 0x1002,
347		0xcc77, 0x2807,
348		0xcc78, 0x31a7,
349		0xcc79, 0x20c4,
350		0xcc7a, 0x3c24,
351		0xcc7b, 0x6724,
352		0xcc7c, 0x1002,
353		0xcc7d, 0x2807,
354		0xcc7e, 0x3187,
355		0xcc7f, 0x20c4,
356		0xcc80, 0x3c24,
357		0xcc81, 0x6724,
358		0xcc82, 0x1002,
359		0xcc83, 0x2514,
360		0xcc84, 0x3c64,
361		0xcc85, 0x6436,
362		0xcc86, 0xdff4,
363		0xcc87, 0x6436,
364		0xcc88, 0x1002,
365		0xcc89, 0x40a4,
366		0xcc8a, 0x643c,
367		0xcc8b, 0x4016,
368		0xcc8c, 0x8c6c,
369		0xcc8d, 0x2b24,
370		0xcc8e, 0x3c24,
371		0xcc8f, 0x6435,
372		0xcc90, 0x1002,
373		0xcc91, 0x2b24,
374		0xcc92, 0x3c24,
375		0xcc93, 0x643a,
376		0xcc94, 0x4025,
377		0xcc95, 0x8a5a,
378		0xcc96, 0x1002,
379		0xcc97, 0x2731,
380		0xcc98, 0x3011,
381		0xcc99, 0x1001,
382		0xcc9a, 0xc7a0,
383		0xcc9b, 0x100,
384		0xcc9c, 0xc502,
385		0xcc9d, 0x53ac,
386		0xcc9e, 0xc503,
387		0xcc9f, 0xd5d5,
388		0xcca0, 0xc600,
389		0xcca1, 0x2a6d,
390		0xcca2, 0xc601,
391		0xcca3, 0x2a4c,
392		0xcca4, 0xc602,
393		0xcca5, 0x111,
394		0xcca6, 0xc60c,
395		0xcca7, 0x5900,
396		0xcca8, 0xc710,
397		0xcca9, 0x700,
398		0xccaa, 0xc718,
399		0xccab, 0x700,
400		0xccac, 0xc720,
401		0xccad, 0x4700,
402		0xccae, 0xc801,
403		0xccaf, 0x7f50,
404		0xccb0, 0xc802,
405		0xccb1, 0x7760,
406		0xccb2, 0xc803,
407		0xccb3, 0x7fce,
408		0xccb4, 0xc804,
409		0xccb5, 0x5700,
410		0xccb6, 0xc805,
411		0xccb7, 0x5f11,
412		0xccb8, 0xc806,
413		0xccb9, 0x4751,
414		0xccba, 0xc807,
415		0xccbb, 0x57e1,
416		0xccbc, 0xc808,
417		0xccbd, 0x2700,
418		0xccbe, 0xc809,
419		0xccbf, 0x000,
420		0xccc0, 0xc821,
421		0xccc1, 0x002,
422		0xccc2, 0xc822,
423		0xccc3, 0x014,
424		0xccc4, 0xc832,
425		0xccc5, 0x1186,
426		0xccc6, 0xc847,
427		0xccc7, 0x1e02,
428		0xccc8, 0xc013,
429		0xccc9, 0xf341,
430		0xccca, 0xc01a,
431		0xcccb, 0x446,
432		0xcccc, 0xc024,
433		0xcccd, 0x1000,
434		0xccce, 0xc025,
435		0xcccf, 0xa00,
436		0xccd0, 0xc026,
437		0xccd1, 0xc0c,
438		0xccd2, 0xc027,
439		0xccd3, 0xc0c,
440		0xccd4, 0xc029,
441		0xccd5, 0x0a0,
442		0xccd6, 0xc030,
443		0xccd7, 0xa00,
444		0xccd8, 0xc03c,
445		0xccd9, 0x01c,
446		0xccda, 0xc005,
447		0xccdb, 0x7a06,
448		0xccdc, 0x000,
449		0xccdd, 0x2731,
450		0xccde, 0x3011,
451		0xccdf, 0x1001,
452		0xcce0, 0xc620,
453		0xcce1, 0x000,
454		0xcce2, 0xc621,
455		0xcce3, 0x03f,
456		0xcce4, 0xc622,
457		0xcce5, 0x000,
458		0xcce6, 0xc623,
459		0xcce7, 0x000,
460		0xcce8, 0xc624,
461		0xcce9, 0x000,
462		0xccea, 0xc625,
463		0xcceb, 0x000,
464		0xccec, 0xc627,
465		0xcced, 0x000,
466		0xccee, 0xc628,
467		0xccef, 0x000,
468		0xccf0, 0xc62c,
469		0xccf1, 0x000,
470		0xccf2, 0x000,
471		0xccf3, 0x2806,
472		0xccf4, 0x3cb6,
473		0xccf5, 0xc161,
474		0xccf6, 0x6134,
475		0xccf7, 0x6135,
476		0xccf8, 0x5443,
477		0xccf9, 0x303,
478		0xccfa, 0x6524,
479		0xccfb, 0x00b,
480		0xccfc, 0x1002,
481		0xccfd, 0x2104,
482		0xccfe, 0x3c24,
483		0xccff, 0x2105,
484		0xcd00, 0x3805,
485		0xcd01, 0x6524,
486		0xcd02, 0xdff4,
487		0xcd03, 0x4005,
488		0xcd04, 0x6524,
489		0xcd05, 0x1002,
490		0xcd06, 0x5dd3,
491		0xcd07, 0x306,
492		0xcd08, 0x2ff7,
493		0xcd09, 0x38f7,
494		0xcd0a, 0x60b7,
495		0xcd0b, 0xdffd,
496		0xcd0c, 0x00a,
497		0xcd0d, 0x1002,
498		0xcd0e, 0
499	};
500	int i, err;
501
502	for (err = i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2)
503		err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i],
504				 sr_edc[i + 1]);
505	return err;
506}
507
508static int ael2005_reset(struct cphy *phy, int wait)
509{
510	static struct reg_val regs0[] = {
511		{ MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 },
512		{ MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 },
513		{ MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 },
514		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
515		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 },
516		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 },
517		{ MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 },
518		{ 0, 0, 0, 0 }
519	};
520	static struct reg_val regs1[] = {
521		{ MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 },
522		{ MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a },
523		{ MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 },
524		{ 0, 0, 0, 0 }
525	};
526	static struct reg_val regs2[] = {
527		{ MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 },
528		{ MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 },
529		{ 0, 0, 0, 0 }
530	};
531
532	int err;
533
534	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0);
535	if (err)
536		return err;
537
538	msleep(125);
539	err = set_phy_regs(phy, regs0);
540	if (err)
541		return err;
542
543	msleep(50);
544	err = set_phy_regs(phy, regs1);
545	if (err)
546		return err;
547
548	msleep(50);
549	err = ael2005_setup_sr_edc(phy);
550	if (err)
551		return err;
552
553	return set_phy_regs(phy, regs2);
554}
555
556#ifdef C99_NOT_SUPPORTED
557static struct cphy_ops ael2005_ops = {
558	ael2005_reset,
559	t3_phy_lasi_intr_enable,
560	t3_phy_lasi_intr_disable,
561	t3_phy_lasi_intr_clear,
562	t3_phy_lasi_intr_handler,
563	NULL,
564	NULL,
565	NULL,
566	NULL,
567	NULL,
568	ael100x_get_link_status,
569	ael1002_power_down,
570};
571#else
572static struct cphy_ops ael2005_ops = {
573	.reset           = ael2005_reset,
574	.intr_enable     = t3_phy_lasi_intr_enable,
575	.intr_disable    = t3_phy_lasi_intr_disable,
576	.intr_clear      = t3_phy_lasi_intr_clear,
577	.intr_handler    = t3_phy_lasi_intr_handler,
578	.get_link_status = ael100x_get_link_status,
579	.power_down      = ael1002_power_down,
580};
581#endif
582
583int t3_ael2005_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
584			const struct mdio_ops *mdio_ops)
585{
586	cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
587		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
588		  "10GBASE-R");
589	msleep(125);
590	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
591				   1 << 5);
592}
593
594#ifdef C99_NOT_SUPPORTED
595static struct cphy_ops qt2045_ops = {
596	ael1006_reset,
597	t3_phy_lasi_intr_enable,
598	t3_phy_lasi_intr_disable,
599	t3_phy_lasi_intr_clear,
600	t3_phy_lasi_intr_handler,
601	NULL,
602	NULL,
603	NULL,
604	NULL,
605	NULL,
606	ael100x_get_link_status,
607	ael1006_power_down,
608};
609#else
610static struct cphy_ops qt2045_ops = {
611	.reset           = ael1006_reset,
612	.intr_enable     = t3_phy_lasi_intr_enable,
613	.intr_disable    = t3_phy_lasi_intr_disable,
614	.intr_clear      = t3_phy_lasi_intr_clear,
615	.intr_handler    = t3_phy_lasi_intr_handler,
616	.get_link_status = ael100x_get_link_status,
617	.power_down      = ael1006_power_down,
618};
619#endif
620
621int t3_qt2045_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
622		       const struct mdio_ops *mdio_ops)
623{
624	unsigned int stat;
625
626	cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops,
627		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
628		  "10GBASE-CX4");
629
630	/*
631	 * Some cards where the PHY is supposed to be at address 0 actually
632	 * have it at 1.
633	 */
634	if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) &&
635	    stat == 0xffff)
636		phy->addr = 1;
637	return 0;
638}
639
640static int xaui_direct_reset(struct cphy *phy, int wait)
641{
642	return 0;
643}
644
645static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
646				       int *speed, int *duplex, int *fc)
647{
648	if (link_ok) {
649		unsigned int status;
650
651		status = t3_read_reg(phy->adapter,
652				     XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
653			 t3_read_reg(phy->adapter,
654				     XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
655			 t3_read_reg(phy->adapter,
656				     XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
657			 t3_read_reg(phy->adapter,
658				     XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
659		*link_ok = !(status & F_LOWSIG0);
660	}
661	if (speed)
662		*speed = SPEED_10000;
663	if (duplex)
664		*duplex = DUPLEX_FULL;
665	return 0;
666}
667
668static int xaui_direct_power_down(struct cphy *phy, int enable)
669{
670	return 0;
671}
672
673#ifdef C99_NOT_SUPPORTED
674static struct cphy_ops xaui_direct_ops = {
675	xaui_direct_reset,
676	ael1002_intr_noop,
677	ael1002_intr_noop,
678	ael1002_intr_noop,
679	ael1002_intr_noop,
680	NULL,
681	NULL,
682	NULL,
683	NULL,
684	NULL,
685	xaui_direct_get_link_status,
686	xaui_direct_power_down,
687};
688#else
689static struct cphy_ops xaui_direct_ops = {
690	.reset           = xaui_direct_reset,
691	.intr_enable     = ael1002_intr_noop,
692	.intr_disable    = ael1002_intr_noop,
693	.intr_clear      = ael1002_intr_noop,
694	.intr_handler    = ael1002_intr_noop,
695	.get_link_status = xaui_direct_get_link_status,
696	.power_down      = xaui_direct_power_down,
697};
698#endif
699
700int t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
701			    const struct mdio_ops *mdio_ops)
702{
703	cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops,
704		  SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP,
705		  "10GBASE-CX4");
706	return 0;
707}
708