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