xref: /freebsd/sys/dev/axgbe/xgbe-mdio.c (revision 9768746b)
1 /*
2  * AMD 10Gb Ethernet driver
3  *
4  * Copyright (c) 2014-2016,2020 Advanced Micro Devices, Inc.
5  *
6  * This file is available to you under your choice of the following two
7  * licenses:
8  *
9  * License 1: GPLv2
10  *
11  * This file is free software; you may copy, redistribute and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 2 of the License, or (at
14  * your option) any later version.
15  *
16  * This file is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  *
24  * This file incorporates work covered by the following copyright and
25  * permission notice:
26  *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
27  *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
28  *     Inc. unless otherwise expressly agreed to in writing between Synopsys
29  *     and you.
30  *
31  *     The Software IS NOT an item of Licensed Software or Licensed Product
32  *     under any End User Software License Agreement or Agreement for Licensed
33  *     Product with Synopsys or any supplement thereto.  Permission is hereby
34  *     granted, free of charge, to any person obtaining a copy of this software
35  *     annotated with this license and the Software, to deal in the Software
36  *     without restriction, including without limitation the rights to use,
37  *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
38  *     of the Software, and to permit persons to whom the Software is furnished
39  *     to do so, subject to the following conditions:
40  *
41  *     The above copyright notice and this permission notice shall be included
42  *     in all copies or substantial portions of the Software.
43  *
44  *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
45  *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
46  *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
47  *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
48  *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
49  *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
50  *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
51  *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53  *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
54  *     THE POSSIBILITY OF SUCH DAMAGE.
55  *
56  *
57  * License 2: Modified BSD
58  *
59  * Redistribution and use in source and binary forms, with or without
60  * modification, are permitted provided that the following conditions are met:
61  *     * Redistributions of source code must retain the above copyright
62  *       notice, this list of conditions and the following disclaimer.
63  *     * Redistributions in binary form must reproduce the above copyright
64  *       notice, this list of conditions and the following disclaimer in the
65  *       documentation and/or other materials provided with the distribution.
66  *     * Neither the name of Advanced Micro Devices, Inc. nor the
67  *       names of its contributors may be used to endorse or promote products
68  *       derived from this software without specific prior written permission.
69  *
70  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
71  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
72  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
73  * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
74  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
75  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
76  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
77  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
78  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
79  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
80  *
81  * This file incorporates work covered by the following copyright and
82  * permission notice:
83  *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
84  *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
85  *     Inc. unless otherwise expressly agreed to in writing between Synopsys
86  *     and you.
87  *
88  *     The Software IS NOT an item of Licensed Software or Licensed Product
89  *     under any End User Software License Agreement or Agreement for Licensed
90  *     Product with Synopsys or any supplement thereto.  Permission is hereby
91  *     granted, free of charge, to any person obtaining a copy of this software
92  *     annotated with this license and the Software, to deal in the Software
93  *     without restriction, including without limitation the rights to use,
94  *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
95  *     of the Software, and to permit persons to whom the Software is furnished
96  *     to do so, subject to the following conditions:
97  *
98  *     The above copyright notice and this permission notice shall be included
99  *     in all copies or substantial portions of the Software.
100  *
101  *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
102  *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
103  *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
104  *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
105  *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
106  *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
107  *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
108  *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
109  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
110  *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
111  *     THE POSSIBILITY OF SUCH DAMAGE.
112  */
113 
114 #include <sys/cdefs.h>
115 __FBSDID("$FreeBSD$");
116 
117 #include "xgbe.h"
118 #include "xgbe-common.h"
119 
120 static void xgbe_an_state_machine(struct xgbe_prv_data *pdata);
121 
122 static void
123 xgbe_an37_clear_interrupts(struct xgbe_prv_data *pdata)
124 {
125 	int reg;
126 
127 	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT);
128 	reg &= ~XGBE_AN_CL37_INT_MASK;
129 	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg);
130 }
131 
132 static void
133 xgbe_an37_disable_interrupts(struct xgbe_prv_data *pdata)
134 {
135 	int reg;
136 
137 	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
138 	reg &= ~XGBE_AN_CL37_INT_MASK;
139 	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
140 
141 	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL);
142 	reg &= ~XGBE_PCS_CL37_BP;
143 	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg);
144 }
145 
146 static void
147 xgbe_an37_enable_interrupts(struct xgbe_prv_data *pdata)
148 {
149 	int reg;
150 
151 	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL);
152 	reg |= XGBE_PCS_CL37_BP;
153 	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg);
154 
155 	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
156 	reg |= XGBE_AN_CL37_INT_MASK;
157 	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
158 }
159 
160 static void
161 xgbe_an73_clear_interrupts(struct xgbe_prv_data *pdata)
162 {
163 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
164 }
165 
166 static void
167 xgbe_an73_disable_interrupts(struct xgbe_prv_data *pdata)
168 {
169 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
170 }
171 
172 static void
173 xgbe_an73_enable_interrupts(struct xgbe_prv_data *pdata)
174 {
175 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_CL73_INT_MASK);
176 }
177 
178 static void
179 xgbe_an_enable_interrupts(struct xgbe_prv_data *pdata)
180 {
181 	switch (pdata->an_mode) {
182 	case XGBE_AN_MODE_CL73:
183 	case XGBE_AN_MODE_CL73_REDRV:
184 		xgbe_an73_enable_interrupts(pdata);
185 		break;
186 	case XGBE_AN_MODE_CL37:
187 	case XGBE_AN_MODE_CL37_SGMII:
188 		xgbe_an37_enable_interrupts(pdata);
189 		break;
190 	default:
191 		break;
192 	}
193 }
194 
195 static void
196 xgbe_an_clear_interrupts_all(struct xgbe_prv_data *pdata)
197 {
198 	xgbe_an73_clear_interrupts(pdata);
199 	xgbe_an37_clear_interrupts(pdata);
200 }
201 
202 static void
203 xgbe_kr_mode(struct xgbe_prv_data *pdata)
204 {
205 	/* Set MAC to 10G speed */
206 	pdata->hw_if.set_speed(pdata, SPEED_10000);
207 
208 	/* Call PHY implementation support to complete rate change */
209 	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KR);
210 }
211 
212 static void
213 xgbe_kx_2500_mode(struct xgbe_prv_data *pdata)
214 {
215 	/* Set MAC to 2.5G speed */
216 	pdata->hw_if.set_speed(pdata, SPEED_2500);
217 
218 	/* Call PHY implementation support to complete rate change */
219 	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_2500);
220 }
221 
222 static void
223 xgbe_kx_1000_mode(struct xgbe_prv_data *pdata)
224 {
225 	/* Set MAC to 1G speed */
226 	pdata->hw_if.set_speed(pdata, SPEED_1000);
227 
228 	/* Call PHY implementation support to complete rate change */
229 	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_1000);
230 }
231 
232 static void
233 xgbe_sfi_mode(struct xgbe_prv_data *pdata)
234 {
235 	/* If a KR re-driver is present, change to KR mode instead */
236 	if (pdata->kr_redrv)
237 		return (xgbe_kr_mode(pdata));
238 
239 	/* Set MAC to 10G speed */
240 	pdata->hw_if.set_speed(pdata, SPEED_10000);
241 
242 	/* Call PHY implementation support to complete rate change */
243 	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SFI);
244 }
245 
246 static void
247 xgbe_x_mode(struct xgbe_prv_data *pdata)
248 {
249 	/* Set MAC to 1G speed */
250 	pdata->hw_if.set_speed(pdata, SPEED_1000);
251 
252 	/* Call PHY implementation support to complete rate change */
253 	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_X);
254 }
255 
256 static void
257 xgbe_sgmii_1000_mode(struct xgbe_prv_data *pdata)
258 {
259 	/* Set MAC to 1G speed */
260 	pdata->hw_if.set_speed(pdata, SPEED_1000);
261 
262 	/* Call PHY implementation support to complete rate change */
263 	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SGMII_1000);
264 }
265 
266 static void
267 xgbe_sgmii_100_mode(struct xgbe_prv_data *pdata)
268 {
269 	/* Set MAC to 1G speed */
270 	pdata->hw_if.set_speed(pdata, SPEED_1000);
271 
272 	/* Call PHY implementation support to complete rate change */
273 	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SGMII_100);
274 }
275 
276 static enum xgbe_mode
277 xgbe_cur_mode(struct xgbe_prv_data *pdata)
278 {
279 	return (pdata->phy_if.phy_impl.cur_mode(pdata));
280 }
281 
282 static bool
283 xgbe_in_kr_mode(struct xgbe_prv_data *pdata)
284 {
285 	return (xgbe_cur_mode(pdata) == XGBE_MODE_KR);
286 }
287 
288 static void
289 xgbe_change_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
290 {
291 	switch (mode) {
292 	case XGBE_MODE_KX_1000:
293 		xgbe_kx_1000_mode(pdata);
294 		break;
295 	case XGBE_MODE_KX_2500:
296 		xgbe_kx_2500_mode(pdata);
297 		break;
298 	case XGBE_MODE_KR:
299 		xgbe_kr_mode(pdata);
300 		break;
301 	case XGBE_MODE_SGMII_100:
302 		xgbe_sgmii_100_mode(pdata);
303 		break;
304 	case XGBE_MODE_SGMII_1000:
305 		xgbe_sgmii_1000_mode(pdata);
306 		break;
307 	case XGBE_MODE_X:
308 		xgbe_x_mode(pdata);
309 		break;
310 	case XGBE_MODE_SFI:
311 		xgbe_sfi_mode(pdata);
312 		break;
313 	case XGBE_MODE_UNKNOWN:
314 		break;
315 	default:
316 		axgbe_error("invalid operation mode requested (%u)\n", mode);
317 	}
318 }
319 
320 static void
321 xgbe_switch_mode(struct xgbe_prv_data *pdata)
322 {
323 	xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata));
324 }
325 
326 static bool
327 xgbe_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
328 {
329 	if (mode == xgbe_cur_mode(pdata))
330 		return (false);
331 
332 	xgbe_change_mode(pdata, mode);
333 
334 	return (true);
335 }
336 
337 static bool
338 xgbe_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
339 {
340 	return (pdata->phy_if.phy_impl.use_mode(pdata, mode));
341 }
342 
343 static void
344 xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable, bool restart)
345 {
346 	unsigned int reg;
347 
348 	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_CTRL1);
349 	reg &= ~MDIO_VEND2_CTRL1_AN_ENABLE;
350 
351 	if (enable)
352 		reg |= MDIO_VEND2_CTRL1_AN_ENABLE;
353 
354 	if (restart)
355 		reg |= MDIO_VEND2_CTRL1_AN_RESTART;
356 
357 	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg);
358 }
359 
360 static void
361 xgbe_an37_restart(struct xgbe_prv_data *pdata)
362 {
363 	xgbe_an37_enable_interrupts(pdata);
364 	xgbe_an37_set(pdata, true, true);
365 }
366 
367 static void
368 xgbe_an37_disable(struct xgbe_prv_data *pdata)
369 {
370 	xgbe_an37_set(pdata, false, false);
371 	xgbe_an37_disable_interrupts(pdata);
372 }
373 
374 static void
375 xgbe_an73_set(struct xgbe_prv_data *pdata, bool enable, bool restart)
376 {
377 	unsigned int reg;
378 
379 	/* Disable KR training for now */
380 	reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
381 	reg &= ~XGBE_KR_TRAINING_ENABLE;
382 	XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
383 
384 	/* Update AN settings */
385 	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1);
386 	reg &= ~MDIO_AN_CTRL1_ENABLE;
387 
388 	if (enable)
389 		reg |= MDIO_AN_CTRL1_ENABLE;
390 
391 	if (restart)
392 		reg |= MDIO_AN_CTRL1_RESTART;
393 
394 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_CTRL1, reg);
395 }
396 
397 static void
398 xgbe_an73_restart(struct xgbe_prv_data *pdata)
399 {
400 	xgbe_an73_enable_interrupts(pdata);
401 	xgbe_an73_set(pdata, true, true);
402 }
403 
404 static void
405 xgbe_an73_disable(struct xgbe_prv_data *pdata)
406 {
407 	xgbe_an73_set(pdata, false, false);
408 	xgbe_an73_disable_interrupts(pdata);
409 
410 	pdata->an_start = 0;
411 }
412 
413 static void
414 xgbe_an_restart(struct xgbe_prv_data *pdata)
415 {
416 	if (pdata->phy_if.phy_impl.an_pre)
417 		pdata->phy_if.phy_impl.an_pre(pdata);
418 
419 	switch (pdata->an_mode) {
420 	case XGBE_AN_MODE_CL73:
421 	case XGBE_AN_MODE_CL73_REDRV:
422 		xgbe_an73_restart(pdata);
423 		break;
424 	case XGBE_AN_MODE_CL37:
425 	case XGBE_AN_MODE_CL37_SGMII:
426 		xgbe_an37_restart(pdata);
427 		break;
428 	default:
429 		break;
430 	}
431 }
432 
433 static void
434 xgbe_an_disable(struct xgbe_prv_data *pdata)
435 {
436 	if (pdata->phy_if.phy_impl.an_post)
437 		pdata->phy_if.phy_impl.an_post(pdata);
438 
439 	switch (pdata->an_mode) {
440 	case XGBE_AN_MODE_CL73:
441 	case XGBE_AN_MODE_CL73_REDRV:
442 		xgbe_an73_disable(pdata);
443 		break;
444 	case XGBE_AN_MODE_CL37:
445 	case XGBE_AN_MODE_CL37_SGMII:
446 		xgbe_an37_disable(pdata);
447 		break;
448 	default:
449 		break;
450 	}
451 }
452 
453 static void
454 xgbe_an_disable_all(struct xgbe_prv_data *pdata)
455 {
456 	xgbe_an73_disable(pdata);
457 	xgbe_an37_disable(pdata);
458 }
459 
460 static enum xgbe_an
461 xgbe_an73_tx_training(struct xgbe_prv_data *pdata, enum xgbe_rx *state)
462 {
463 	unsigned int ad_reg, lp_reg, reg;
464 
465 	*state = XGBE_RX_COMPLETE;
466 
467 	/* If we're not in KR mode then we're done */
468 	if (!xgbe_in_kr_mode(pdata))
469 		return (XGBE_AN_PAGE_RECEIVED);
470 
471 	/* Enable/Disable FEC */
472 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
473 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
474 
475 	reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL);
476 	reg &= ~(MDIO_PMA_10GBR_FECABLE_ABLE | MDIO_PMA_10GBR_FECABLE_ERRABLE);
477 	if ((ad_reg & 0xc000) && (lp_reg & 0xc000))
478 		reg |= pdata->fec_ability;
479 
480 	XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL, reg);
481 
482 	/* Start KR training */
483 	if (pdata->phy_if.phy_impl.kr_training_pre)
484 		pdata->phy_if.phy_impl.kr_training_pre(pdata);
485 
486 	/* Start KR training */
487 	reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
488 	reg |= XGBE_KR_TRAINING_ENABLE;
489 	reg |= XGBE_KR_TRAINING_START;
490 	XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
491 
492 	if (pdata->phy_if.phy_impl.kr_training_post)
493 		pdata->phy_if.phy_impl.kr_training_post(pdata);
494 
495 	return (XGBE_AN_PAGE_RECEIVED);
496 }
497 
498 static enum xgbe_an
499 xgbe_an73_tx_xnp(struct xgbe_prv_data *pdata, enum xgbe_rx *state)
500 {
501 	uint16_t msg;
502 
503 	*state = XGBE_RX_XNP;
504 
505 	msg = XGBE_XNP_MCF_NULL_MESSAGE;
506 	msg |= XGBE_XNP_MP_FORMATTED;
507 
508 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP + 2, 0);
509 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP + 1, 0);
510 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP, msg);
511 
512 	return (XGBE_AN_PAGE_RECEIVED);
513 }
514 
515 static enum xgbe_an
516 xgbe_an73_rx_bpa(struct xgbe_prv_data *pdata, enum xgbe_rx *state)
517 {
518 	unsigned int link_support;
519 	unsigned int reg, ad_reg, lp_reg;
520 
521 	/* Read Base Ability register 2 first */
522 	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
523 
524 	/* Check for a supported mode, otherwise restart in a different one */
525 	link_support = xgbe_in_kr_mode(pdata) ? 0x80 : 0x20;
526 	if (!(reg & link_support))
527 		return (XGBE_AN_INCOMPAT_LINK);
528 
529 	/* Check Extended Next Page support */
530 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
531 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
532 
533 	return (((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
534 		(lp_reg & XGBE_XNP_NP_EXCHANGE))
535 	       ? xgbe_an73_tx_xnp(pdata, state)
536 	       : xgbe_an73_tx_training(pdata, state));
537 }
538 
539 static enum xgbe_an
540 xgbe_an73_rx_xnp(struct xgbe_prv_data *pdata, enum xgbe_rx *state)
541 {
542 	unsigned int ad_reg, lp_reg;
543 
544 	/* Check Extended Next Page support */
545 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_XNP);
546 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPX);
547 
548 	return (((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
549 		(lp_reg & XGBE_XNP_NP_EXCHANGE))
550 	       ? xgbe_an73_tx_xnp(pdata, state)
551 	       : xgbe_an73_tx_training(pdata, state));
552 }
553 
554 static enum xgbe_an
555 xgbe_an73_page_received(struct xgbe_prv_data *pdata)
556 {
557 	enum xgbe_rx *state;
558 	unsigned long an_timeout;
559 	enum xgbe_an ret;
560 
561 	if (!pdata->an_start) {
562 		pdata->an_start = ticks;
563 	} else {
564 		an_timeout = pdata->an_start +
565 		    ((uint64_t)XGBE_AN_MS_TIMEOUT * (uint64_t)hz) / 1000ull;
566 		if ((int)(ticks - an_timeout) > 0) {
567 			/* Auto-negotiation timed out, reset state */
568 			pdata->kr_state = XGBE_RX_BPA;
569 			pdata->kx_state = XGBE_RX_BPA;
570 
571 			pdata->an_start = ticks;
572 
573 			axgbe_printf(2, "CL73 AN timed out, resetting state\n");
574 		}
575 	}
576 
577 	state = xgbe_in_kr_mode(pdata) ? &pdata->kr_state : &pdata->kx_state;
578 
579 	switch (*state) {
580 	case XGBE_RX_BPA:
581 		ret = xgbe_an73_rx_bpa(pdata, state);
582 		break;
583 
584 	case XGBE_RX_XNP:
585 		ret = xgbe_an73_rx_xnp(pdata, state);
586 		break;
587 
588 	default:
589 		ret = XGBE_AN_ERROR;
590 	}
591 
592 	return (ret);
593 }
594 
595 static enum xgbe_an
596 xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
597 {
598 	/* Be sure we aren't looping trying to negotiate */
599 	if (xgbe_in_kr_mode(pdata)) {
600 		pdata->kr_state = XGBE_RX_ERROR;
601 
602 		if (!(XGBE_ADV(&pdata->phy, 1000baseKX_Full)) &&
603 		    !(XGBE_ADV(&pdata->phy, 2500baseX_Full)))
604 			return (XGBE_AN_NO_LINK);
605 
606 		if (pdata->kx_state != XGBE_RX_BPA)
607 			return (XGBE_AN_NO_LINK);
608 	} else {
609 		pdata->kx_state = XGBE_RX_ERROR;
610 
611 		if (!(XGBE_ADV(&pdata->phy, 10000baseKR_Full)))
612 			return (XGBE_AN_NO_LINK);
613 
614 		if (pdata->kr_state != XGBE_RX_BPA)
615 			return (XGBE_AN_NO_LINK);
616 	}
617 
618 	xgbe_an_disable(pdata);
619 
620 	xgbe_switch_mode(pdata);
621 
622 	xgbe_an_restart(pdata);
623 
624 	return (XGBE_AN_INCOMPAT_LINK);
625 }
626 
627 static void
628 xgbe_an37_isr(struct xgbe_prv_data *pdata)
629 {
630 	unsigned int reg;
631 
632 	/* Disable AN interrupts */
633 	xgbe_an37_disable_interrupts(pdata);
634 
635 	/* Save the interrupt(s) that fired */
636 	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT);
637 	pdata->an_int = reg & XGBE_AN_CL37_INT_MASK;
638 	pdata->an_status = reg & ~XGBE_AN_CL37_INT_MASK;
639 
640 	if (pdata->an_int) {
641 		/* Clear the interrupt(s) that fired and process them */
642 		reg &= ~XGBE_AN_CL37_INT_MASK;
643 		XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg);
644 
645 		xgbe_an_state_machine(pdata);
646 	} else {
647 		/* Enable AN interrupts */
648 		xgbe_an37_enable_interrupts(pdata);
649 
650 		/* Reissue interrupt if status is not clear */
651 		if (pdata->vdata->irq_reissue_support)
652 			XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3);
653 	}
654 }
655 
656 static void
657 xgbe_an73_isr(struct xgbe_prv_data *pdata)
658 {
659 	/* Disable AN interrupts */
660 	xgbe_an73_disable_interrupts(pdata);
661 
662 	/* Save the interrupt(s) that fired */
663 	pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT);
664 
665 	if (pdata->an_int) {
666 		/* Clear the interrupt(s) that fired and process them */
667 		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
668 
669 		xgbe_an_state_machine(pdata);
670 	} else {
671 		/* Enable AN interrupts */
672 		xgbe_an73_enable_interrupts(pdata);
673 
674 		/* Reissue interrupt if status is not clear */
675 		if (pdata->vdata->irq_reissue_support)
676 			XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3);
677 	}
678 }
679 
680 static void
681 xgbe_an_isr_task(unsigned long data)
682 {
683 	struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
684 
685 	axgbe_printf(2, "AN interrupt received\n");
686 
687 	switch (pdata->an_mode) {
688 	case XGBE_AN_MODE_CL73:
689 	case XGBE_AN_MODE_CL73_REDRV:
690 		xgbe_an73_isr(pdata);
691 		break;
692 	case XGBE_AN_MODE_CL37:
693 	case XGBE_AN_MODE_CL37_SGMII:
694 		xgbe_an37_isr(pdata);
695 		break;
696 	default:
697 		break;
698 	}
699 }
700 
701 static void
702 xgbe_an_combined_isr(struct xgbe_prv_data *pdata)
703 {
704 	xgbe_an_isr_task((unsigned long)pdata);
705 }
706 
707 static const char *
708 xgbe_state_as_string(enum xgbe_an state)
709 {
710 	switch (state) {
711 	case XGBE_AN_READY:
712 		return ("Ready");
713 	case XGBE_AN_PAGE_RECEIVED:
714 		return ("Page-Received");
715 	case XGBE_AN_INCOMPAT_LINK:
716 		return ("Incompatible-Link");
717 	case XGBE_AN_COMPLETE:
718 		return ("Complete");
719 	case XGBE_AN_NO_LINK:
720 		return ("No-Link");
721 	case XGBE_AN_ERROR:
722 		return ("Error");
723 	default:
724 		return ("Undefined");
725 	}
726 }
727 
728 static void
729 xgbe_an37_state_machine(struct xgbe_prv_data *pdata)
730 {
731 	enum xgbe_an cur_state = pdata->an_state;
732 
733 	if (!pdata->an_int)
734 		return;
735 
736 	if (pdata->an_int & XGBE_AN_CL37_INT_CMPLT) {
737 		pdata->an_state = XGBE_AN_COMPLETE;
738 		pdata->an_int &= ~XGBE_AN_CL37_INT_CMPLT;
739 
740 		/* If SGMII is enabled, check the link status */
741 		if ((pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) &&
742 		    !(pdata->an_status & XGBE_SGMII_AN_LINK_STATUS))
743 			pdata->an_state = XGBE_AN_NO_LINK;
744 	}
745 
746 	axgbe_printf(2, "%s: CL37 AN %s\n", __func__,
747 	    xgbe_state_as_string(pdata->an_state));
748 
749 	cur_state = pdata->an_state;
750 
751 	switch (pdata->an_state) {
752 	case XGBE_AN_READY:
753 		break;
754 
755 	case XGBE_AN_COMPLETE:
756 		axgbe_printf(2, "Auto negotiation successful\n");
757 		break;
758 
759 	case XGBE_AN_NO_LINK:
760 		break;
761 
762 	default:
763 		pdata->an_state = XGBE_AN_ERROR;
764 	}
765 
766 	if (pdata->an_state == XGBE_AN_ERROR) {
767 		axgbe_printf(2, "error during auto-negotiation, state=%u\n",
768 		    cur_state);
769 
770 		pdata->an_int = 0;
771 		xgbe_an37_clear_interrupts(pdata);
772 	}
773 
774 	if (pdata->an_state >= XGBE_AN_COMPLETE) {
775 		pdata->an_result = pdata->an_state;
776 		pdata->an_state = XGBE_AN_READY;
777 
778 		if (pdata->phy_if.phy_impl.an_post)
779 			pdata->phy_if.phy_impl.an_post(pdata);
780 
781 		axgbe_printf(2, "CL37 AN result: %s\n",
782 		    xgbe_state_as_string(pdata->an_result));
783 	}
784 
785 	axgbe_printf(2, "%s: an_state %d an_int %d an_mode %d an_status %d\n",
786 	     __func__, pdata->an_state, pdata->an_int, pdata->an_mode,
787 	     pdata->an_status);
788 
789 	xgbe_an37_enable_interrupts(pdata);
790 }
791 
792 static void
793 xgbe_an73_state_machine(struct xgbe_prv_data *pdata)
794 {
795 	enum xgbe_an cur_state = pdata->an_state;
796 
797 	if (!pdata->an_int)
798 		goto out;
799 
800 next_int:
801 	if (pdata->an_int & XGBE_AN_CL73_PG_RCV) {
802 		pdata->an_state = XGBE_AN_PAGE_RECEIVED;
803 		pdata->an_int &= ~XGBE_AN_CL73_PG_RCV;
804 	} else if (pdata->an_int & XGBE_AN_CL73_INC_LINK) {
805 		pdata->an_state = XGBE_AN_INCOMPAT_LINK;
806 		pdata->an_int &= ~XGBE_AN_CL73_INC_LINK;
807 	} else if (pdata->an_int & XGBE_AN_CL73_INT_CMPLT) {
808 		pdata->an_state = XGBE_AN_COMPLETE;
809 		pdata->an_int &= ~XGBE_AN_CL73_INT_CMPLT;
810 	} else {
811 		pdata->an_state = XGBE_AN_ERROR;
812 	}
813 
814 again:
815 	axgbe_printf(2, "CL73 AN %s\n",
816 	    xgbe_state_as_string(pdata->an_state));
817 
818 	cur_state = pdata->an_state;
819 
820 	switch (pdata->an_state) {
821 	case XGBE_AN_READY:
822 		pdata->an_supported = 0;
823 		break;
824 
825 	case XGBE_AN_PAGE_RECEIVED:
826 		pdata->an_state = xgbe_an73_page_received(pdata);
827 		pdata->an_supported++;
828 		break;
829 
830 	case XGBE_AN_INCOMPAT_LINK:
831 		pdata->an_supported = 0;
832 		pdata->parallel_detect = 0;
833 		pdata->an_state = xgbe_an73_incompat_link(pdata);
834 		break;
835 
836 	case XGBE_AN_COMPLETE:
837 		pdata->parallel_detect = pdata->an_supported ? 0 : 1;
838 		axgbe_printf(2, "%s successful\n",
839 		    pdata->an_supported ? "Auto negotiation"
840 		    : "Parallel detection");
841 		break;
842 
843 	case XGBE_AN_NO_LINK:
844 		break;
845 
846 	default:
847 		pdata->an_state = XGBE_AN_ERROR;
848 	}
849 
850 	if (pdata->an_state == XGBE_AN_NO_LINK) {
851 		pdata->an_int = 0;
852 		xgbe_an73_clear_interrupts(pdata);
853 	} else if (pdata->an_state == XGBE_AN_ERROR) {
854 		axgbe_printf(2,
855 		    "error during auto-negotiation, state=%u\n",
856 		    cur_state);
857 
858 		pdata->an_int = 0;
859 		xgbe_an73_clear_interrupts(pdata);
860 	}
861 
862 	if (pdata->an_state >= XGBE_AN_COMPLETE) {
863 		pdata->an_result = pdata->an_state;
864 		pdata->an_state = XGBE_AN_READY;
865 		pdata->kr_state = XGBE_RX_BPA;
866 		pdata->kx_state = XGBE_RX_BPA;
867 		pdata->an_start = 0;
868 
869 		if (pdata->phy_if.phy_impl.an_post)
870 			pdata->phy_if.phy_impl.an_post(pdata);
871 
872 		axgbe_printf(2,  "CL73 AN result: %s\n",
873 		    xgbe_state_as_string(pdata->an_result));
874 	}
875 
876 	if (cur_state != pdata->an_state)
877 		goto again;
878 
879 	if (pdata->an_int)
880 		goto next_int;
881 
882 out:
883 	/* Enable AN interrupts on the way out */
884 	xgbe_an73_enable_interrupts(pdata);
885 }
886 
887 static void
888 xgbe_an_state_machine(struct xgbe_prv_data *pdata)
889 {
890 	sx_xlock(&pdata->an_mutex);
891 
892 	switch (pdata->an_mode) {
893 	case XGBE_AN_MODE_CL73:
894 	case XGBE_AN_MODE_CL73_REDRV:
895 		xgbe_an73_state_machine(pdata);
896 		break;
897 	case XGBE_AN_MODE_CL37:
898 	case XGBE_AN_MODE_CL37_SGMII:
899 		xgbe_an37_state_machine(pdata);
900 		break;
901 	default:
902 		break;
903 	}
904 
905 	/* Reissue interrupt if status is not clear */
906 	if (pdata->vdata->irq_reissue_support)
907 		XP_IOWRITE(pdata, XP_INT_REISSUE_EN, 1 << 3);
908 
909 	sx_xunlock(&pdata->an_mutex);
910 }
911 
912 static void
913 xgbe_an37_init(struct xgbe_prv_data *pdata)
914 {
915 	struct xgbe_phy local_phy;
916 	unsigned int reg;
917 
918 	pdata->phy_if.phy_impl.an_advertising(pdata, &local_phy);
919 
920 	axgbe_printf(2, "%s: advertising 0x%x\n", __func__, local_phy.advertising);
921 
922 	/* Set up Advertisement register */
923 	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE);
924 	if (XGBE_ADV(&local_phy, Pause))
925 		reg |= 0x100;
926 	else
927 		reg &= ~0x100;
928 
929 	if (XGBE_ADV(&local_phy, Asym_Pause))
930 		reg |= 0x80;
931 	else
932 		reg &= ~0x80;
933 
934 	/* Full duplex, but not half */
935 	reg |= XGBE_AN_CL37_FD_MASK;
936 	reg &= ~XGBE_AN_CL37_HD_MASK;
937 
938 	axgbe_printf(2, "%s: Writing reg: 0x%x\n", __func__, reg);
939 	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE, reg);
940 
941 	/* Set up the Control register */
942 	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
943 	axgbe_printf(2, "%s: AN_ADVERTISE reg 0x%x an_mode %d\n", __func__,
944 	    reg, pdata->an_mode);
945 	reg &= ~XGBE_AN_CL37_TX_CONFIG_MASK;
946 	reg &= ~XGBE_AN_CL37_PCS_MODE_MASK;
947 
948 	switch (pdata->an_mode) {
949 	case XGBE_AN_MODE_CL37:
950 		reg |= XGBE_AN_CL37_PCS_MODE_BASEX;
951 		break;
952 	case XGBE_AN_MODE_CL37_SGMII:
953 		reg |= XGBE_AN_CL37_PCS_MODE_SGMII;
954 		break;
955 	default:
956 		break;
957 	}
958 
959 	reg |= XGBE_AN_CL37_MII_CTRL_8BIT;
960 	axgbe_printf(2, "%s: Writing reg: 0x%x\n", __func__, reg);
961 	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
962 
963 	axgbe_printf(2, "CL37 AN (%s) initialized\n",
964 	    (pdata->an_mode == XGBE_AN_MODE_CL37) ? "BaseX" : "SGMII");
965 }
966 
967 static void
968 xgbe_an73_init(struct xgbe_prv_data *pdata)
969 {
970 	/*
971 	 * This local_phy is needed because phy-v2 alters the
972 	 * advertising flag variable. so phy-v1 an_advertising is just copying
973 	 */
974 	struct xgbe_phy local_phy;
975 	unsigned int reg;
976 
977 	pdata->phy_if.phy_impl.an_advertising(pdata, &local_phy);
978 
979 	/* Set up Advertisement register 3 first */
980 	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
981 	if (XGBE_ADV(&local_phy, 10000baseR_FEC))
982 		reg |= 0xc000;
983 	else
984 		reg &= ~0xc000;
985 
986 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2, reg);
987 
988 	/* Set up Advertisement register 2 next */
989 	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
990 	if (XGBE_ADV(&local_phy, 10000baseKR_Full))
991 		reg |= 0x80;
992 	else
993 		reg &= ~0x80;
994 
995 	if (XGBE_ADV(&local_phy, 1000baseKX_Full) ||
996 	    XGBE_ADV(&local_phy, 2500baseX_Full))
997 		reg |= 0x20;
998 	else
999 		reg &= ~0x20;
1000 
1001 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1, reg);
1002 
1003 	/* Set up Advertisement register 1 last */
1004 	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
1005 	if (XGBE_ADV(&local_phy, Pause))
1006 		reg |= 0x400;
1007 	else
1008 		reg &= ~0x400;
1009 
1010 	if (XGBE_ADV(&local_phy, Asym_Pause))
1011 		reg |= 0x800;
1012 	else
1013 		reg &= ~0x800;
1014 
1015 	/* We don't intend to perform XNP */
1016 	reg &= ~XGBE_XNP_NP_EXCHANGE;
1017 
1018 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
1019 
1020 	axgbe_printf(2, "CL73 AN initialized\n");
1021 }
1022 
1023 static void
1024 xgbe_an_init(struct xgbe_prv_data *pdata)
1025 {
1026 	/* Set up advertisement registers based on current settings */
1027 	pdata->an_mode = pdata->phy_if.phy_impl.an_mode(pdata);
1028 	axgbe_printf(2, "%s: setting up an_mode %d\n", __func__, pdata->an_mode);
1029 
1030 	switch (pdata->an_mode) {
1031 	case XGBE_AN_MODE_CL73:
1032 	case XGBE_AN_MODE_CL73_REDRV:
1033 		xgbe_an73_init(pdata);
1034 		break;
1035 	case XGBE_AN_MODE_CL37:
1036 	case XGBE_AN_MODE_CL37_SGMII:
1037 		xgbe_an37_init(pdata);
1038 		break;
1039 	default:
1040 		break;
1041 	}
1042 }
1043 
1044 static const char *
1045 xgbe_phy_fc_string(struct xgbe_prv_data *pdata)
1046 {
1047 	if (pdata->tx_pause && pdata->rx_pause)
1048 		return ("rx/tx");
1049 	else if (pdata->rx_pause)
1050 		return ("rx");
1051 	else if (pdata->tx_pause)
1052 		return ("tx");
1053 	else
1054 		return ("off");
1055 }
1056 
1057 static const char *
1058 xgbe_phy_speed_string(int speed)
1059 {
1060 	switch (speed) {
1061 	case SPEED_100:
1062 		return ("100Mbps");
1063 	case SPEED_1000:
1064 		return ("1Gbps");
1065 	case SPEED_2500:
1066 		return ("2.5Gbps");
1067 	case SPEED_10000:
1068 		return ("10Gbps");
1069 	case SPEED_UNKNOWN:
1070 		return ("Unknown");
1071 	default:
1072 		return ("Unsupported");
1073 	}
1074 }
1075 
1076 static void
1077 xgbe_phy_print_status(struct xgbe_prv_data *pdata)
1078 {
1079 	if (pdata->phy.link)
1080 		axgbe_printf(0,
1081 		    "Link is UP - %s/%s - flow control %s\n",
1082 		    xgbe_phy_speed_string(pdata->phy.speed),
1083 		    pdata->phy.duplex == DUPLEX_FULL ? "Full" : "Half",
1084 		    xgbe_phy_fc_string(pdata));
1085 	else
1086 		axgbe_printf(0, "Link is DOWN\n");
1087 }
1088 
1089 static void
1090 xgbe_phy_adjust_link(struct xgbe_prv_data *pdata)
1091 {
1092 	int new_state = 0;
1093 
1094 	axgbe_printf(1, "link %d/%d tx %d/%d rx %d/%d speed %d/%d autoneg %d/%d\n",
1095 	    pdata->phy_link, pdata->phy.link,
1096 	    pdata->tx_pause, pdata->phy.tx_pause,
1097 	    pdata->rx_pause, pdata->phy.rx_pause,
1098 	    pdata->phy_speed, pdata->phy.speed,
1099 	    pdata->pause_autoneg, pdata->phy.pause_autoneg);
1100 
1101 	if (pdata->phy.link) {
1102 		/* Flow control support */
1103 		pdata->pause_autoneg = pdata->phy.pause_autoneg;
1104 
1105 		if (pdata->tx_pause != pdata->phy.tx_pause) {
1106 			new_state = 1;
1107 			axgbe_printf(2, "tx pause %d/%d\n", pdata->tx_pause,
1108 			    pdata->phy.tx_pause);
1109 			pdata->tx_pause = pdata->phy.tx_pause;
1110 			pdata->hw_if.config_tx_flow_control(pdata);
1111 		}
1112 
1113 		if (pdata->rx_pause != pdata->phy.rx_pause) {
1114 			new_state = 1;
1115 			axgbe_printf(2, "rx pause %d/%d\n", pdata->rx_pause,
1116 			    pdata->phy.rx_pause);
1117 			pdata->rx_pause = pdata->phy.rx_pause;
1118 			pdata->hw_if.config_rx_flow_control(pdata);
1119 		}
1120 
1121 		/* Speed support */
1122 		if (pdata->phy_speed != pdata->phy.speed) {
1123 			new_state = 1;
1124 			pdata->phy_speed = pdata->phy.speed;
1125 		}
1126 
1127 		if (pdata->phy_link != pdata->phy.link) {
1128 			new_state = 1;
1129 			pdata->phy_link = pdata->phy.link;
1130 		}
1131 	} else if (pdata->phy_link) {
1132 		new_state = 1;
1133 		pdata->phy_link = 0;
1134 		pdata->phy_speed = SPEED_UNKNOWN;
1135 	}
1136 
1137 	axgbe_printf(2, "phy_link %d Link %d new_state %d\n", pdata->phy_link,
1138 	    pdata->phy.link, new_state);
1139 
1140 	if (new_state)
1141 		xgbe_phy_print_status(pdata);
1142 }
1143 
1144 static bool
1145 xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
1146 {
1147 	return (pdata->phy_if.phy_impl.valid_speed(pdata, speed));
1148 }
1149 
1150 static int
1151 xgbe_phy_config_fixed(struct xgbe_prv_data *pdata)
1152 {
1153 	enum xgbe_mode mode;
1154 
1155 	axgbe_printf(2, "fixed PHY configuration\n");
1156 
1157 	/* Disable auto-negotiation */
1158 	xgbe_an_disable(pdata);
1159 
1160 	/* Set specified mode for specified speed */
1161 	mode = pdata->phy_if.phy_impl.get_mode(pdata, pdata->phy.speed);
1162 	switch (mode) {
1163 	case XGBE_MODE_KX_1000:
1164 	case XGBE_MODE_KX_2500:
1165 	case XGBE_MODE_KR:
1166 	case XGBE_MODE_SGMII_100:
1167 	case XGBE_MODE_SGMII_1000:
1168 	case XGBE_MODE_X:
1169 	case XGBE_MODE_SFI:
1170 		break;
1171 	case XGBE_MODE_UNKNOWN:
1172 	default:
1173 		return (-EINVAL);
1174 	}
1175 
1176 	/* Validate duplex mode */
1177 	if (pdata->phy.duplex != DUPLEX_FULL)
1178 		return (-EINVAL);
1179 
1180 	xgbe_set_mode(pdata, mode);
1181 
1182 	return (0);
1183 }
1184 
1185 static int
1186 __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata, bool set_mode)
1187 {
1188 	int ret;
1189 	unsigned int reg = 0;
1190 
1191 	sx_xlock(&pdata->an_mutex);
1192 
1193 	set_bit(XGBE_LINK_INIT, &pdata->dev_state);
1194 	pdata->link_check = ticks;
1195 
1196 	ret = pdata->phy_if.phy_impl.an_config(pdata);
1197 	if (ret) {
1198 		axgbe_error("%s: an_config fail %d\n", __func__, ret);
1199 		goto out;
1200 	}
1201 
1202 	if (pdata->phy.autoneg != AUTONEG_ENABLE) {
1203 		ret = xgbe_phy_config_fixed(pdata);
1204 		if (ret || !pdata->kr_redrv) {
1205 			if (ret)
1206 				axgbe_error("%s: fix conf fail %d\n", __func__, ret);
1207 			goto out;
1208 		}
1209 
1210 		axgbe_printf(2, "AN redriver support\n");
1211 	} else
1212 		axgbe_printf(2, "AN PHY configuration\n");
1213 
1214 	/* Disable auto-negotiation interrupt */
1215 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
1216 	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK);
1217 	axgbe_printf(2, "%s: set_mode %d AN int reg value 0x%x\n", __func__,
1218 	    set_mode, reg);
1219 
1220 	/* Clear any auto-negotitation interrupts */
1221 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
1222 
1223 	/* Start auto-negotiation in a supported mode */
1224 	if (set_mode) {
1225 		/* Start auto-negotiation in a supported mode */
1226 		if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
1227 			xgbe_set_mode(pdata, XGBE_MODE_KR);
1228 		} else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
1229 			xgbe_set_mode(pdata, XGBE_MODE_KX_2500);
1230 		} else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
1231 			xgbe_set_mode(pdata, XGBE_MODE_KX_1000);
1232 		} else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) {
1233 			xgbe_set_mode(pdata, XGBE_MODE_SFI);
1234 		} else if (xgbe_use_mode(pdata, XGBE_MODE_X)) {
1235 			xgbe_set_mode(pdata, XGBE_MODE_X);
1236 		} else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) {
1237 			xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000);
1238 		} else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
1239 			xgbe_set_mode(pdata, XGBE_MODE_SGMII_100);
1240 		} else {
1241 			XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0x07);
1242 			ret = -EINVAL;
1243 			goto out;
1244 		}
1245 	}
1246 
1247 	/* Disable and stop any in progress auto-negotiation */
1248 	xgbe_an_disable_all(pdata);
1249 
1250 	/* Clear any auto-negotitation interrupts */
1251 	xgbe_an_clear_interrupts_all(pdata);
1252 
1253 	pdata->an_result = XGBE_AN_READY;
1254 	pdata->an_state = XGBE_AN_READY;
1255 	pdata->kr_state = XGBE_RX_BPA;
1256 	pdata->kx_state = XGBE_RX_BPA;
1257 
1258 	/* Re-enable auto-negotiation interrupt */
1259 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0x07);
1260 	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK);
1261 
1262 	/* Set up advertisement registers based on current settings */
1263 	xgbe_an_init(pdata);
1264 
1265 	/* Enable and start auto-negotiation */
1266 	xgbe_an_restart(pdata);
1267 
1268 out:
1269 	if (ret) {
1270 		axgbe_printf(0, "%s: set_mode %d AN int reg value 0x%x ret value %d\n",
1271 		   __func__, set_mode, reg, ret);
1272 		set_bit(XGBE_LINK_ERR, &pdata->dev_state);
1273 	} else
1274 		clear_bit(XGBE_LINK_ERR, &pdata->dev_state);
1275 
1276 	sx_unlock(&pdata->an_mutex);
1277 
1278 	return (ret);
1279 }
1280 
1281 static int
1282 xgbe_phy_config_aneg(struct xgbe_prv_data *pdata)
1283 {
1284 	return (__xgbe_phy_config_aneg(pdata, true));
1285 }
1286 
1287 static int
1288 xgbe_phy_reconfig_aneg(struct xgbe_prv_data *pdata)
1289 {
1290 	return (__xgbe_phy_config_aneg(pdata, false));
1291 }
1292 
1293 static bool
1294 xgbe_phy_aneg_done(struct xgbe_prv_data *pdata)
1295 {
1296 	return (pdata->an_result == XGBE_AN_COMPLETE);
1297 }
1298 
1299 static void
1300 xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
1301 {
1302 	unsigned long link_timeout;
1303 
1304 	link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * hz);
1305 	if ((int)(ticks - link_timeout) > 0) {
1306 		axgbe_printf(2, "AN link timeout\n");
1307 		xgbe_phy_config_aneg(pdata);
1308 	}
1309 }
1310 
1311 static enum xgbe_mode
1312 xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
1313 {
1314 	return (pdata->phy_if.phy_impl.an_outcome(pdata));
1315 }
1316 
1317 static void
1318 xgbe_phy_status_result(struct xgbe_prv_data *pdata)
1319 {
1320 	enum xgbe_mode mode;
1321 
1322 	XGBE_ZERO_LP_ADV(&pdata->phy);
1323 
1324 	if ((pdata->phy.autoneg != AUTONEG_ENABLE) || pdata->parallel_detect)
1325 		mode = xgbe_cur_mode(pdata);
1326 	else
1327 		mode = xgbe_phy_status_aneg(pdata);
1328 
1329 	axgbe_printf(3, "%s: xgbe mode %d\n", __func__, mode);
1330 	switch (mode) {
1331 	case XGBE_MODE_SGMII_100:
1332 		pdata->phy.speed = SPEED_100;
1333 		break;
1334 	case XGBE_MODE_X:
1335 	case XGBE_MODE_KX_1000:
1336 	case XGBE_MODE_SGMII_1000:
1337 		pdata->phy.speed = SPEED_1000;
1338 		break;
1339 	case XGBE_MODE_KX_2500:
1340 		pdata->phy.speed = SPEED_2500;
1341 		break;
1342 	case XGBE_MODE_KR:
1343 	case XGBE_MODE_SFI:
1344 		pdata->phy.speed = SPEED_10000;
1345 		break;
1346 	case XGBE_MODE_UNKNOWN:
1347 	default:
1348 		axgbe_printf(1, "%s: unknown mode\n", __func__);
1349 		pdata->phy.speed = SPEED_UNKNOWN;
1350 	}
1351 
1352 	pdata->phy.duplex = DUPLEX_FULL;
1353 	axgbe_printf(2, "%s: speed %d duplex %d\n", __func__, pdata->phy.speed,
1354 	    pdata->phy.duplex);
1355 
1356 	if (xgbe_set_mode(pdata, mode) && pdata->an_again)
1357 		xgbe_phy_reconfig_aneg(pdata);
1358 }
1359 
1360 static void
1361 xgbe_phy_status(struct xgbe_prv_data *pdata)
1362 {
1363 	bool link_aneg;
1364 	int an_restart;
1365 
1366 	if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) {
1367 		axgbe_error("%s: LINK_ERR\n", __func__);
1368 		pdata->phy.link = 0;
1369 		goto adjust_link;
1370 	}
1371 
1372 	link_aneg = (pdata->phy.autoneg == AUTONEG_ENABLE);
1373 	axgbe_printf(3, "link_aneg - %d\n", link_aneg);
1374 
1375 	/* Get the link status. Link status is latched low, so read
1376 	 * once to clear and then read again to get current state
1377 	 */
1378 	pdata->phy.link = pdata->phy_if.phy_impl.link_status(pdata,
1379 	    &an_restart);
1380 
1381 	axgbe_printf(1, "link_status returned Link:%d an_restart:%d aneg:%d\n",
1382 	    pdata->phy.link, an_restart, link_aneg);
1383 
1384 	if (an_restart) {
1385 		xgbe_phy_config_aneg(pdata);
1386 		return;
1387 	}
1388 
1389 	if (pdata->phy.link) {
1390 		axgbe_printf(2, "Link Active\n");
1391 		if (link_aneg && !xgbe_phy_aneg_done(pdata)) {
1392 			axgbe_printf(1, "phy_link set check timeout\n");
1393 			xgbe_check_link_timeout(pdata);
1394 			return;
1395 		}
1396 
1397 		axgbe_printf(2, "%s: Link write phy_status result\n", __func__);
1398 		xgbe_phy_status_result(pdata);
1399 
1400 		if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
1401 			clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
1402 
1403 	} else {
1404 		axgbe_printf(2, "Link Deactive\n");
1405 		if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) {
1406 			axgbe_printf(1, "phy_link not set check timeout\n");
1407 			xgbe_check_link_timeout(pdata);
1408 
1409 			if (link_aneg) {
1410 				axgbe_printf(2, "link_aneg case\n");
1411 				return;
1412 			}
1413 		}
1414 
1415 		xgbe_phy_status_result(pdata);
1416 
1417 	}
1418 
1419 adjust_link:
1420 	axgbe_printf(2, "%s: Link %d\n", __func__, pdata->phy.link);
1421 	xgbe_phy_adjust_link(pdata);
1422 }
1423 
1424 static void
1425 xgbe_phy_stop(struct xgbe_prv_data *pdata)
1426 {
1427 	axgbe_printf(2, "stopping PHY\n");
1428 
1429 	if (!pdata->phy_started)
1430 		return;
1431 
1432 	/* Indicate the PHY is down */
1433 	pdata->phy_started = 0;
1434 
1435 	/* Disable auto-negotiation */
1436 	xgbe_an_disable_all(pdata);
1437 
1438 	pdata->phy_if.phy_impl.stop(pdata);
1439 
1440 	pdata->phy.link = 0;
1441 
1442 	xgbe_phy_adjust_link(pdata);
1443 }
1444 
1445 static int
1446 xgbe_phy_start(struct xgbe_prv_data *pdata)
1447 {
1448 	int ret;
1449 
1450 	DBGPR("-->xgbe_phy_start\n");
1451 
1452 	ret = pdata->phy_if.phy_impl.start(pdata);
1453 	if (ret) {
1454 		axgbe_error("%s: impl start ret %d\n", __func__, ret);
1455 		return (ret);
1456 	}
1457 
1458 	/* Set initial mode - call the mode setting routines
1459 	 * directly to insure we are properly configured
1460 	 */
1461 	if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
1462 		axgbe_printf(2, "%s: KR\n", __func__);
1463 		xgbe_kr_mode(pdata);
1464 	} else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
1465 		axgbe_printf(2, "%s: KX 2500\n", __func__);
1466 		xgbe_kx_2500_mode(pdata);
1467 	} else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
1468 		axgbe_printf(2, "%s: KX 1000\n", __func__);
1469 		xgbe_kx_1000_mode(pdata);
1470 	} else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) {
1471 		axgbe_printf(2, "%s: SFI\n", __func__);
1472 		xgbe_sfi_mode(pdata);
1473 	} else if (xgbe_use_mode(pdata, XGBE_MODE_X)) {
1474 		axgbe_printf(2, "%s: X\n", __func__);
1475 		xgbe_x_mode(pdata);
1476 	} else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) {
1477 		axgbe_printf(2, "%s: SGMII 1000\n", __func__);
1478 		xgbe_sgmii_1000_mode(pdata);
1479 	} else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
1480 		axgbe_printf(2, "%s: SGMII 100\n", __func__);
1481 		xgbe_sgmii_100_mode(pdata);
1482 	} else {
1483 		axgbe_error("%s: invalid mode\n", __func__);
1484 		ret = -EINVAL;
1485 		goto err_stop;
1486 	}
1487 
1488 	/* Indicate the PHY is up and running */
1489 	pdata->phy_started = 1;
1490 
1491 	/* Set up advertisement registers based on current settings */
1492 	xgbe_an_init(pdata);
1493 
1494 	/* Enable auto-negotiation interrupts */
1495 	xgbe_an_enable_interrupts(pdata);
1496 
1497 	ret = xgbe_phy_config_aneg(pdata);
1498 	if (ret)
1499 		axgbe_error("%s: phy_config_aneg %d\n", __func__, ret);
1500 
1501 	return (ret);
1502 
1503 err_stop:
1504 	pdata->phy_if.phy_impl.stop(pdata);
1505 
1506 	return (ret);
1507 }
1508 
1509 static int
1510 xgbe_phy_reset(struct xgbe_prv_data *pdata)
1511 {
1512 	int ret;
1513 
1514 	ret = pdata->phy_if.phy_impl.reset(pdata);
1515 	if (ret) {
1516 		axgbe_error("%s: impl phy reset %d\n", __func__, ret);
1517 		return (ret);
1518 	}
1519 
1520 	/* Disable auto-negotiation for now */
1521 	xgbe_an_disable_all(pdata);
1522 
1523 	/* Clear auto-negotiation interrupts */
1524 	xgbe_an_clear_interrupts_all(pdata);
1525 
1526 	return (0);
1527 }
1528 
1529 static int
1530 xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata)
1531 {
1532 
1533 	if (XGBE_ADV(&pdata->phy, 10000baseKR_Full))
1534 		return (SPEED_10000);
1535 	else if (XGBE_ADV(&pdata->phy, 10000baseT_Full))
1536 		return (SPEED_10000);
1537 	else if (XGBE_ADV(&pdata->phy, 2500baseX_Full))
1538 		return (SPEED_2500);
1539 	else if (XGBE_ADV(&pdata->phy, 2500baseT_Full))
1540 		return (SPEED_2500);
1541 	else if (XGBE_ADV(&pdata->phy, 1000baseKX_Full))
1542 		return (SPEED_1000);
1543 	else if (XGBE_ADV(&pdata->phy, 1000baseT_Full))
1544 		return (SPEED_1000);
1545 	else if (XGBE_ADV(&pdata->phy, 100baseT_Full))
1546 		return (SPEED_100);
1547 
1548 	return (SPEED_UNKNOWN);
1549 }
1550 
1551 static void
1552 xgbe_phy_exit(struct xgbe_prv_data *pdata)
1553 {
1554 	pdata->phy_if.phy_impl.exit(pdata);
1555 }
1556 
1557 static int
1558 xgbe_phy_init(struct xgbe_prv_data *pdata)
1559 {
1560 	int ret = 0;
1561 
1562 	DBGPR("-->xgbe_phy_init\n");
1563 
1564 	sx_init(&pdata->an_mutex, "axgbe AN lock");
1565 	pdata->mdio_mmd = MDIO_MMD_PCS;
1566 
1567 	/* Initialize supported features */
1568 	pdata->fec_ability = XMDIO_READ(pdata, MDIO_MMD_PMAPMD,
1569 					MDIO_PMA_10GBR_FECABLE);
1570 	pdata->fec_ability &= (MDIO_PMA_10GBR_FECABLE_ABLE |
1571 			       MDIO_PMA_10GBR_FECABLE_ERRABLE);
1572 
1573 	/* Setup the phy (including supported features) */
1574 	ret = pdata->phy_if.phy_impl.init(pdata);
1575 	if (ret)
1576 		return (ret);
1577 
1578 	/* Copy supported link modes to advertising link modes */
1579 	XGBE_LM_COPY(&pdata->phy, advertising, &pdata->phy, supported);
1580 
1581 	pdata->phy.address = 0;
1582 
1583 	if (XGBE_ADV(&pdata->phy, Autoneg)) {
1584 		pdata->phy.autoneg = AUTONEG_ENABLE;
1585 		pdata->phy.speed = SPEED_UNKNOWN;
1586 		pdata->phy.duplex = DUPLEX_UNKNOWN;
1587 	} else {
1588 		pdata->phy.autoneg = AUTONEG_DISABLE;
1589 		pdata->phy.speed = xgbe_phy_best_advertised_speed(pdata);
1590 		pdata->phy.duplex = DUPLEX_FULL;
1591 	}
1592 
1593 	pdata->phy.link = 0;
1594 
1595 	pdata->phy.pause_autoneg = pdata->pause_autoneg;
1596 	pdata->phy.tx_pause = pdata->tx_pause;
1597 	pdata->phy.rx_pause = pdata->rx_pause;
1598 
1599 	/* Fix up Flow Control advertising */
1600 	XGBE_CLR_ADV(&pdata->phy, Pause);
1601 	XGBE_CLR_ADV(&pdata->phy, Asym_Pause);
1602 
1603 	if (pdata->rx_pause) {
1604 		XGBE_SET_ADV(&pdata->phy, Pause);
1605 		XGBE_SET_ADV(&pdata->phy, Asym_Pause);
1606 	}
1607 
1608 	if (pdata->tx_pause) {
1609 		if (XGBE_ADV(&pdata->phy, Asym_Pause))
1610 			XGBE_CLR_ADV(&pdata->phy, Asym_Pause);
1611 		else
1612 			XGBE_SET_ADV(&pdata->phy, Asym_Pause);
1613 	}
1614 
1615 	return (0);
1616 }
1617 
1618 void
1619 xgbe_init_function_ptrs_phy(struct xgbe_phy_if *phy_if)
1620 {
1621 	phy_if->phy_init	= xgbe_phy_init;
1622 	phy_if->phy_exit	= xgbe_phy_exit;
1623 
1624 	phy_if->phy_reset       = xgbe_phy_reset;
1625 	phy_if->phy_start       = xgbe_phy_start;
1626 	phy_if->phy_stop	= xgbe_phy_stop;
1627 
1628 	phy_if->phy_status      = xgbe_phy_status;
1629 	phy_if->phy_config_aneg = xgbe_phy_config_aneg;
1630 
1631 	phy_if->phy_valid_speed = xgbe_phy_valid_speed;
1632 
1633 	phy_if->an_isr		= xgbe_an_combined_isr;
1634 }
1635