1197791Snp/**************************************************************************
2197791Snp
3197791SnpCopyright (c) 2009 Chelsio Inc.
4197791SnpAll rights reserved.
5197791Snp
6197791SnpRedistribution and use in source and binary forms, with or without
7197791Snpmodification, are permitted provided that the following conditions are met:
8197791Snp
9197791Snp 1. Redistributions of source code must retain the above copyright notice,
10197791Snp    this list of conditions and the following disclaimer.
11197791Snp
12197791Snp 2. Neither the name of the Chelsio Corporation nor the names of its
13197791Snp    contributors may be used to endorse or promote products derived from
14197791Snp    this software without specific prior written permission.
15197791Snp
16197791SnpTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17197791SnpAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18197791SnpIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19197791SnpARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20197791SnpLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21197791SnpCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22197791SnpSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23197791SnpINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24197791SnpCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25197791SnpARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26197791SnpPOSSIBILITY OF SUCH DAMAGE.
27197791Snp
28197791Snp***************************************************************************/
29197791Snp
30197791Snp#include <sys/cdefs.h>
31197791Snp__FBSDID("$FreeBSD$");
32197791Snp
33197791Snp#include <cxgb_include.h>
34197791Snp
35197791Snp#undef msleep
36197791Snp#define msleep t3_os_sleep
37197791Snp
38197791Snpenum {
39197791Snp	/* MDIO_DEV_PMA_PMD registers */
40197791Snp	AQ_LINK_STAT	= 0xe800,
41197791Snp
42197791Snp	/* MDIO_DEV_XGXS registers */
43197791Snp	AQ_XAUI_RX_CFG	= 0xc400,
44197791Snp	AQ_XAUI_KX_CFG	= 0xc440,
45197791Snp	AQ_XAUI_TX_CFG	= 0xe400,
46197791Snp
47197791Snp	/* MDIO_DEV_ANEG registers */
48197791Snp	AQ_100M_CTRL	= 0x0010,
49197791Snp	AQ_10G_CTRL	= 0x0020,
50197791Snp	AQ_1G_CTRL	= 0xc400,
51197791Snp	AQ_ANEG_STAT	= 0xc800,
52197791Snp
53197791Snp	/* MDIO_DEV_VEND1 registers */
54197791Snp	AQ_FW_VERSION	= 0x0020,
55197791Snp	AQ_THERMAL_THR	= 0xc421,
56197791Snp	AQ_THERMAL1	= 0xc820,
57197791Snp	AQ_THERMAL2	= 0xc821,
58197791Snp	AQ_IFLAG_GLOBAL	= 0xfc00,
59197791Snp	AQ_IMASK_GLOBAL	= 0xff00,
60197791Snp};
61197791Snp
62197791Snp#define AQBIT(x)	(1 << (0x##x))
63197791Snp#define ADV_1G_FULL	AQBIT(f)
64197791Snp#define ADV_1G_HALF	AQBIT(e)
65197791Snp#define ADV_10G_FULL	AQBIT(c)
66197791Snp
67197791Snp#define AQ_WRITE_REGS(phy, regs) do { \
68197791Snp	int i; \
69197791Snp	for (i = 0; i < ARRAY_SIZE(regs); i++) { \
70197791Snp		(void) mdio_write(phy, regs[i].mmd, regs[i].reg, regs[i].val); \
71197791Snp	} \
72197791Snp} while (0)
73197791Snp#define AQ_READ_REGS(phy, regs) do { \
74197791Snp	unsigned i, v; \
75197791Snp	for (i = 0; i < ARRAY_SIZE(regs); i++) { \
76197791Snp		(void) mdio_read(phy, regs[i].mmd, regs[i].reg, &v); \
77197791Snp	} \
78197791Snp} while (0)
79197791Snp
80197791Snp/*
81197791Snp * Return value is temperature in celcius, 0xffff for error or don't know.
82197791Snp */
83197791Snpstatic int
84197791Snpaq100x_temperature(struct cphy *phy)
85197791Snp{
86197791Snp	unsigned int v;
87197791Snp
88197791Snp	if (mdio_read(phy, MDIO_DEV_VEND1, AQ_THERMAL2, &v) ||
89197791Snp	    v == 0xffff || (v & 1) != 1)
90197791Snp		return (0xffff);
91197791Snp
92197791Snp	if (mdio_read(phy, MDIO_DEV_VEND1, AQ_THERMAL1, &v))
93197791Snp		return (0xffff);
94197791Snp
95197791Snp	return ((int)((signed char)(v >> 8)));
96197791Snp}
97197791Snp
98197791Snpstatic int
99197791Snpaq100x_set_defaults(struct cphy *phy)
100197791Snp{
101197791Snp	return mdio_write(phy, MDIO_DEV_VEND1, AQ_THERMAL_THR, 0x6c00);
102197791Snp}
103197791Snp
104197791Snpstatic int
105197791Snpaq100x_reset(struct cphy *phy, int wait)
106197791Snp{
107197791Snp	int err;
108197791Snp	err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
109197791Snp	if (!err)
110197791Snp		err = aq100x_set_defaults(phy);
111197791Snp	return (err);
112197791Snp}
113197791Snp
114197791Snpstatic int
115197791Snpaq100x_intr_enable(struct cphy *phy)
116197791Snp{
117197791Snp	struct {
118197791Snp		int mmd;
119197791Snp		int reg;
120197791Snp		int val;
121197791Snp	} imasks[] = {
122197791Snp		{MDIO_DEV_VEND1, 0xd400, AQBIT(e)},
123197791Snp		{MDIO_DEV_VEND1, 0xff01, AQBIT(2)},
124197791Snp		{MDIO_DEV_VEND1, AQ_IMASK_GLOBAL, AQBIT(0)}
125197791Snp	};
126197791Snp
127197791Snp	AQ_WRITE_REGS(phy, imasks);
128197791Snp
129197791Snp	return (0);
130197791Snp}
131197791Snp
132197791Snpstatic int
133197791Snpaq100x_intr_disable(struct cphy *phy)
134197791Snp{
135197791Snp	struct {
136197791Snp		int mmd;
137197791Snp		int reg;
138197791Snp		int val;
139197791Snp	} imasks[] = {
140197791Snp		{MDIO_DEV_VEND1, 0xd400, 0},
141197791Snp		{MDIO_DEV_VEND1, 0xff01, 0},
142197791Snp		{MDIO_DEV_VEND1, AQ_IMASK_GLOBAL, 0}
143197791Snp	};
144197791Snp
145197791Snp	AQ_WRITE_REGS(phy, imasks);
146197791Snp
147197791Snp	return (0);
148197791Snp}
149197791Snp
150197791Snpstatic int
151197791Snpaq100x_intr_clear(struct cphy *phy)
152197791Snp{
153197791Snp	struct {
154197791Snp		int mmd;
155197791Snp		int reg;
156197791Snp	} iclr[] = {
157197791Snp		{MDIO_DEV_VEND1, 0xcc00},
158197791Snp		{MDIO_DEV_VEND1, AQ_IMASK_GLOBAL} /* needed? */
159197791Snp	};
160197791Snp
161197791Snp	AQ_READ_REGS(phy, iclr);
162197791Snp
163197791Snp	return (0);
164197791Snp}
165197791Snp
166197791Snpstatic int
167197791Snpaq100x_vendor_intr(struct cphy *phy, int *rc)
168197791Snp{
169197791Snp	int err;
170197791Snp	unsigned int cause, v;
171197791Snp
172197791Snp	err = mdio_read(phy, MDIO_DEV_VEND1, 0xfc01, &cause);
173197791Snp	if (err)
174197791Snp		return (err);
175197791Snp
176197791Snp	if (cause & AQBIT(2)) {
177197791Snp		err = mdio_read(phy, MDIO_DEV_VEND1, 0xcc00, &v);
178197791Snp		if (err)
179197791Snp			return (err);
180197791Snp
181197791Snp		if (v & AQBIT(e)) {
182197791Snp			CH_WARN(phy->adapter, "PHY%d: temperature is now %dC\n",
183197791Snp			    phy->addr, aq100x_temperature(phy));
184197791Snp
185197791Snp			t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
186197791Snp			    phy->addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL, 0);
187197791Snp
188197791Snp			*rc |= cphy_cause_alarm;
189197791Snp		}
190197791Snp
191197791Snp		cause &= ~4;
192197791Snp	}
193197791Snp
194197791Snp	if (cause)
195197791Snp		CH_WARN(phy->adapter, "PHY%d: unhandled vendor interrupt"
196197791Snp		    " (0x%x)\n", phy->addr, cause);
197197791Snp
198197791Snp	return (0);
199197791Snp
200197791Snp}
201197791Snp
202197791Snpstatic int
203197791Snpaq100x_intr_handler(struct cphy *phy)
204197791Snp{
205197791Snp	int err, rc = 0;
206197791Snp	unsigned int cause;
207197791Snp
208197791Snp	err = mdio_read(phy, MDIO_DEV_VEND1, AQ_IFLAG_GLOBAL, &cause);
209197791Snp	if (err)
210197791Snp		return (err);
211197791Snp
212197791Snp	if (cause & AQBIT(0)) {
213197791Snp		err = aq100x_vendor_intr(phy, &rc);
214197791Snp		if (err)
215197791Snp			return (err);
216197791Snp		cause &= ~AQBIT(0);
217197791Snp	}
218197791Snp
219197791Snp	if (cause)
220197791Snp		CH_WARN(phy->adapter, "PHY%d: unhandled interrupt (0x%x)\n",
221197791Snp		    phy->addr, cause);
222197791Snp
223197791Snp	return (rc);
224197791Snp}
225197791Snp
226197791Snpstatic int
227197791Snpaq100x_power_down(struct cphy *phy, int off)
228197791Snp{
229197791Snp	int err, wait = 500;
230197791Snp	unsigned int v;
231197791Snp
232197791Snp	err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, BMCR_PDOWN,
233197791Snp	    off ? BMCR_PDOWN : 0);
234197791Snp	if (err || off)
235228825Snp		return (err);
236197791Snp
237197791Snp	msleep(300);
238197791Snp	do {
239197791Snp		err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
240197791Snp		if (err)
241197791Snp			return (err);
242197791Snp		v &= BMCR_RESET;
243197791Snp		if (v)
244197791Snp			msleep(10);
245197791Snp	} while (v && --wait);
246197791Snp	if (v) {
247197791Snp		CH_WARN(phy->adapter, "PHY%d: power-up timed out (0x%x).\n",
248197791Snp		    phy->addr, v);
249197791Snp		return (ETIMEDOUT);
250197791Snp	}
251197791Snp
252197791Snp	return (0);
253197791Snp}
254197791Snp
255197791Snpstatic int
256197791Snpaq100x_autoneg_enable(struct cphy *phy)
257197791Snp{
258197791Snp	int err;
259197791Snp
260197791Snp	err = aq100x_power_down(phy, 0);
261197791Snp	if (!err)
262197791Snp		err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR,
263197791Snp		    BMCR_RESET, BMCR_ANENABLE | BMCR_ANRESTART);
264197791Snp
265197791Snp	return (err);
266197791Snp}
267197791Snp
268197791Snpstatic int
269197791Snpaq100x_autoneg_restart(struct cphy *phy)
270197791Snp{
271197791Snp	return aq100x_autoneg_enable(phy);
272197791Snp}
273197791Snp
274197791Snpstatic int
275197791Snpaq100x_advertise(struct cphy *phy, unsigned int advertise_map)
276197791Snp{
277197791Snp	unsigned int adv;
278197791Snp	int err;
279197791Snp
280197791Snp	/* 10G advertisement */
281197791Snp	adv = 0;
282197791Snp	if (advertise_map & ADVERTISED_10000baseT_Full)
283197791Snp		adv |= ADV_10G_FULL;
284197791Snp	err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_10G_CTRL,
285197791Snp				  ADV_10G_FULL, adv);
286197791Snp	if (err)
287197791Snp		return (err);
288197791Snp
289197791Snp	/* 1G advertisement */
290197791Snp	adv = 0;
291197791Snp	if (advertise_map & ADVERTISED_1000baseT_Full)
292197791Snp		adv |= ADV_1G_FULL;
293197791Snp	if (advertise_map & ADVERTISED_1000baseT_Half)
294197791Snp		adv |= ADV_1G_HALF;
295197791Snp	err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_1G_CTRL,
296197791Snp				  ADV_1G_FULL | ADV_1G_HALF, adv);
297197791Snp	if (err)
298197791Snp		return (err);
299197791Snp
300197791Snp	/* 100M, pause advertisement */
301197791Snp	adv = 0;
302197791Snp	if (advertise_map & ADVERTISED_100baseT_Half)
303197791Snp		adv |= ADVERTISE_100HALF;
304197791Snp	if (advertise_map & ADVERTISED_100baseT_Full)
305197791Snp		adv |= ADVERTISE_100FULL;
306197791Snp	if (advertise_map & ADVERTISED_Pause)
307197791Snp		adv |= ADVERTISE_PAUSE_CAP;
308197791Snp	if (advertise_map & ADVERTISED_Asym_Pause)
309197791Snp		adv |= ADVERTISE_PAUSE_ASYM;
310197791Snp	err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_100M_CTRL, 0xfe0, adv);
311197791Snp
312197791Snp	return (err);
313197791Snp}
314197791Snp
315197791Snpstatic int
316197791Snpaq100x_set_loopback(struct cphy *phy, int mmd, int dir, int enable)
317197791Snp{
318197791Snp	return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
319197791Snp				   BMCR_LOOPBACK, enable ? BMCR_LOOPBACK : 0);
320197791Snp}
321197791Snp
322197791Snpstatic int
323197791Snpaq100x_set_speed_duplex(struct cphy *phy, int speed, int duplex)
324197791Snp{
325197791Snp	int err, set;
326197791Snp
327197791Snp	if (speed == SPEED_100)
328197791Snp		set = BMCR_SPEED100;
329197791Snp	else if (speed == SPEED_1000)
330197791Snp		set = BMCR_SPEED1000;
331197791Snp	else if (speed == SPEED_10000)
332197791Snp		set = BMCR_SPEED1000 | BMCR_SPEED100;
333197791Snp	else
334197791Snp		return (EINVAL);
335197791Snp
336197791Snp	if (duplex != DUPLEX_FULL)
337197791Snp		return (EINVAL);
338197791Snp
339197791Snp	err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR,
340197791Snp	    BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART, 0);
341197791Snp	if (err)
342197791Snp		return (err);
343197791Snp
344197791Snp	err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
345197791Snp	    BMCR_SPEED1000 | BMCR_SPEED100, set);
346197791Snp	if (err)
347197791Snp		return (err);
348197791Snp
349197791Snp	return (0);
350197791Snp}
351197791Snp
352197791Snpstatic int
353197791Snpaq100x_get_link_status(struct cphy *phy, int *link_ok, int *speed, int *duplex,
354197791Snp		       int *fc)
355197791Snp{
356197791Snp	int err;
357197791Snp	unsigned int v, link = 0;
358197791Snp
359197791Snp	err = mdio_read(phy, MDIO_DEV_PMA_PMD, AQ_LINK_STAT, &v);
360197791Snp	if (err)
361197791Snp		return (err);
362197791Snp	if (v == 0xffff || !(v & 1))
363197791Snp		goto done;
364197791Snp
365197791Snp	err = mdio_read(phy, MDIO_DEV_ANEG, MII_BMCR, &v);
366197791Snp	if (err)
367197791Snp		return (err);
368197791Snp	if (v & 0x8000)
369197791Snp		goto done;
370197791Snp	if (v & BMCR_ANENABLE) {
371197791Snp
372197791Snp		err = mdio_read(phy, MDIO_DEV_ANEG, 1, &v);
373197791Snp		if (err)
374197791Snp			return (err);
375197791Snp		if ((v & 0x20) == 0)
376197791Snp			goto done;
377197791Snp
378197791Snp		err = mdio_read(phy, MDIO_DEV_ANEG, AQ_ANEG_STAT, &v);
379197791Snp		if (err)
380197791Snp			return (err);
381197791Snp
382197791Snp		if (speed) {
383197791Snp			switch (v & 0x6) {
384197791Snp			case 0x6: *speed = SPEED_10000;
385197791Snp				break;
386197791Snp			case 0x4: *speed = SPEED_1000;
387197791Snp				break;
388197791Snp			case 0x2: *speed = SPEED_100;
389197791Snp				break;
390197791Snp			case 0x0: *speed = SPEED_10;
391197791Snp				break;
392197791Snp			}
393197791Snp		}
394197791Snp
395197791Snp		if (duplex)
396197791Snp			*duplex = v & 1 ? DUPLEX_FULL : DUPLEX_HALF;
397197791Snp
398197791Snp		if (fc) {
399197791Snp			unsigned int lpa, adv;
400197791Snp			err = mdio_read(phy, MDIO_DEV_ANEG, 0x13, &lpa);
401197791Snp			if (!err)
402197791Snp				err = mdio_read(phy, MDIO_DEV_ANEG,
403197791Snp				    AQ_100M_CTRL, &adv);
404197791Snp			if (err)
405197791Snp				return err;
406197791Snp
407197791Snp			if (lpa & adv & ADVERTISE_PAUSE_CAP)
408197791Snp				*fc = PAUSE_RX | PAUSE_TX;
409197791Snp			else if (lpa & ADVERTISE_PAUSE_CAP &&
410197791Snp			    lpa & ADVERTISE_PAUSE_ASYM &&
411197791Snp			    adv & ADVERTISE_PAUSE_ASYM)
412197791Snp				*fc = PAUSE_TX;
413197791Snp			else if (lpa & ADVERTISE_PAUSE_ASYM &&
414197791Snp			    adv & ADVERTISE_PAUSE_CAP)
415197791Snp				*fc = PAUSE_RX;
416197791Snp			else
417197791Snp				*fc = 0;
418197791Snp		}
419197791Snp
420197791Snp	} else {
421197791Snp		err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
422197791Snp		if (err)
423197791Snp			return (err);
424197791Snp
425197791Snp		v &= BMCR_SPEED1000 | BMCR_SPEED100;
426197791Snp		if (speed) {
427197791Snp			if (v == (BMCR_SPEED1000 | BMCR_SPEED100))
428197791Snp				*speed = SPEED_10000;
429197791Snp			else if (v == BMCR_SPEED1000)
430197791Snp				*speed = SPEED_1000;
431197791Snp			else if (v == BMCR_SPEED100)
432197791Snp				*speed = SPEED_100;
433197791Snp			else
434197791Snp				*speed = SPEED_10;
435197791Snp		}
436197791Snp
437197791Snp		if (duplex)
438197791Snp			*duplex = DUPLEX_FULL;
439197791Snp	}
440197791Snp
441197791Snp	link = 1;
442197791Snpdone:
443197791Snp	if (link_ok)
444197791Snp		*link_ok = link;
445197791Snp	return (0);
446197791Snp}
447197791Snp
448197791Snpstatic struct cphy_ops aq100x_ops = {
449197791Snp	.reset             = aq100x_reset,
450197791Snp	.intr_enable       = aq100x_intr_enable,
451197791Snp	.intr_disable      = aq100x_intr_disable,
452197791Snp	.intr_clear        = aq100x_intr_clear,
453197791Snp	.intr_handler      = aq100x_intr_handler,
454197791Snp	.autoneg_enable    = aq100x_autoneg_enable,
455197791Snp	.autoneg_restart   = aq100x_autoneg_restart,
456197791Snp	.advertise         = aq100x_advertise,
457197791Snp	.set_loopback      = aq100x_set_loopback,
458197791Snp	.set_speed_duplex  = aq100x_set_speed_duplex,
459197791Snp	.get_link_status   = aq100x_get_link_status,
460197791Snp	.power_down        = aq100x_power_down,
461197791Snp};
462197791Snp
463197791Snpint
464197791Snpt3_aq100x_phy_prep(pinfo_t *pinfo, int phy_addr,
465197791Snp		       const struct mdio_ops *mdio_ops)
466197791Snp{
467197791Snp	struct cphy *phy = &pinfo->phy;
468197791Snp	unsigned int v, v2, gpio, wait;
469197791Snp	int err;
470197791Snp	adapter_t *adapter = pinfo->adapter;
471197791Snp
472197791Snp	cphy_init(&pinfo->phy, adapter, pinfo, phy_addr, &aq100x_ops, mdio_ops,
473197791Snp		  SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
474197791Snp		  SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI |
475197791Snp		  SUPPORTED_MISC_IRQ, "1000/10GBASE-T");
476197791Snp
477197791Snp	/*
478197791Snp	 * Hard reset the PHY.
479197791Snp	 */
480197791Snp	gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL;
481197791Snp	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0);
482197791Snp	msleep(1);
483197791Snp	t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio);
484197791Snp
485197791Snp	/*
486197791Snp	 * Give it enough time to load the firmware and get ready for mdio.
487197791Snp	 */
488197791Snp	msleep(1000);
489197791Snp	wait = 500; /* in 10ms increments */
490197791Snp	do {
491197791Snp		err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
492197791Snp		if (err || v == 0xffff) {
493197791Snp
494197791Snp			/* Allow prep_adapter to succeed when ffff is read */
495197791Snp
496197791Snp			CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n",
497197791Snp				phy_addr, err, v);
498197791Snp			goto done;
499197791Snp		}
500197791Snp
501197791Snp		v &= BMCR_RESET;
502197791Snp		if (v)
503197791Snp			msleep(10);
504197791Snp	} while (v && --wait);
505197791Snp	if (v) {
506197791Snp		CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n",
507197791Snp			phy_addr, v);
508197791Snp
509197791Snp		goto done; /* let prep_adapter succeed */
510197791Snp	}
511197791Snp
512197791Snp	/* Firmware version check. */
513197791Snp	(void) mdio_read(phy, MDIO_DEV_VEND1, AQ_FW_VERSION, &v);
514197791Snp	if (v < 0x115)
515197791Snp		CH_WARN(adapter, "PHY%d: unknown firmware %d.%d\n", phy_addr,
516197791Snp		    v >> 8, v & 0xff);
517197791Snp
518197791Snp	/* The PHY should start in really-low-power mode. */
519197791Snp	(void) mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
520197791Snp	if ((v & BMCR_PDOWN) == 0)
521197791Snp		CH_WARN(adapter, "PHY%d does not start in low power mode.\n",
522197791Snp			phy_addr);
523197791Snp
524197791Snp	/*
525197791Snp	 * Verify XAUI and 1000-X settings, but let prep succeed no matter what.
526197791Snp	 */
527197791Snp	v = v2 = 0;
528197791Snp	(void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_RX_CFG, &v);
529197791Snp	(void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_TX_CFG, &v2);
530197791Snp	if (v != 0x1b || v2 != 0x1b)
531197791Snp		CH_WARN(adapter, "PHY%d: incorrect XAUI settings "
532197791Snp		    "(0x%x, 0x%x).\n", phy_addr, v, v2);
533197791Snp	v = 0;
534197791Snp	(void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_KX_CFG, &v);
535197791Snp	if ((v & 0xf) != 0xf)
536197791Snp		CH_WARN(adapter, "PHY%d: incorrect 1000-X settings "
537197791Snp		    "(0x%x).\n", phy_addr, v);
538197791Snp
539197791Snp	(void) aq100x_set_defaults(phy);
540197791Snpdone:
541197791Snp	return (err);
542197791Snp}
543