]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
amd-xgbe: Prepare for working with more than one type of phy
[mirror_ubuntu-artful-kernel.git] / drivers / net / ethernet / amd / xgbe / xgbe-mdio.c
CommitLineData
c5aa9e3b
LT
1/*
2 * AMD 10Gb Ethernet driver
3 *
4 * This file is available to you under your choice of the following two
5 * licenses:
6 *
7 * License 1: GPLv2
8 *
ced3fcae 9 * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
c5aa9e3b
LT
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 *
ced3fcae 59 * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
c5aa9e3b
LT
60 * All rights reserved.
61 *
62 * Redistribution and use in source and binary forms, with or without
63 * modification, are permitted provided that the following conditions are met:
64 * * Redistributions of source code must retain the above copyright
65 * notice, this list of conditions and the following disclaimer.
66 * * Redistributions in binary form must reproduce the above copyright
67 * notice, this list of conditions and the following disclaimer in the
68 * documentation and/or other materials provided with the distribution.
69 * * Neither the name of Advanced Micro Devices, Inc. nor the
70 * names of its contributors may be used to endorse or promote products
71 * derived from this software without specific prior written permission.
72 *
73 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
74 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
75 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
76 * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
77 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
78 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
79 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
80 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
81 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
82 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
83 *
84 * This file incorporates work covered by the following copyright and
85 * permission notice:
86 * The Synopsys DWC ETHER XGMAC Software Driver and documentation
87 * (hereinafter "Software") is an unsupported proprietary work of Synopsys,
88 * Inc. unless otherwise expressly agreed to in writing between Synopsys
89 * and you.
90 *
91 * The Software IS NOT an item of Licensed Software or Licensed Product
92 * under any End User Software License Agreement or Agreement for Licensed
93 * Product with Synopsys or any supplement thereto. Permission is hereby
94 * granted, free of charge, to any person obtaining a copy of this software
95 * annotated with this license and the Software, to deal in the Software
96 * without restriction, including without limitation the rights to use,
97 * copy, modify, merge, publish, distribute, sublicense, and/or sell copies
98 * of the Software, and to permit persons to whom the Software is furnished
99 * to do so, subject to the following conditions:
100 *
101 * The above copyright notice and this permission notice shall be included
102 * in all copies or substantial portions of the Software.
103 *
104 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
105 * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
106 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
107 * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
108 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
109 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
110 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
111 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
112 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
113 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
114 * THE POSSIBILITY OF SUCH DAMAGE.
115 */
116
117#include <linux/module.h>
118#include <linux/kmod.h>
c5aa9e3b
LT
119#include <linux/mdio.h>
120#include <linux/phy.h>
121#include <linux/of.h>
7c12aa08
LT
122#include <linux/bitops.h>
123#include <linux/jiffies.h>
c5aa9e3b
LT
124
125#include "xgbe.h"
126#include "xgbe-common.h"
127
7c12aa08 128static void xgbe_an_enable_kr_training(struct xgbe_prv_data *pdata)
c5aa9e3b 129{
7c12aa08 130 unsigned int reg;
c5aa9e3b 131
7c12aa08 132 reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
c5aa9e3b 133
7c12aa08
LT
134 reg |= XGBE_KR_TRAINING_ENABLE;
135 XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
136}
137
138static void xgbe_an_disable_kr_training(struct xgbe_prv_data *pdata)
139{
140 unsigned int reg;
141
142 reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
143
144 reg &= ~XGBE_KR_TRAINING_ENABLE;
145 XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
146}
147
e57f7a3f 148static void xgbe_kr_mode(struct xgbe_prv_data *pdata)
7c12aa08 149{
7c12aa08
LT
150 /* Enable KR training */
151 xgbe_an_enable_kr_training(pdata);
152
153 /* Set MAC to 10G speed */
e57f7a3f
LT
154 pdata->hw_if.set_speed(pdata, SPEED_10000);
155
156 /* Call PHY implementation support to complete rate change */
157 pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KR);
7c12aa08
LT
158}
159
e57f7a3f 160static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata)
7c12aa08 161{
7c12aa08
LT
162 /* Disable KR training */
163 xgbe_an_disable_kr_training(pdata);
164
165 /* Set MAC to 2.5G speed */
e57f7a3f
LT
166 pdata->hw_if.set_speed(pdata, SPEED_2500);
167
168 /* Call PHY implementation support to complete rate change */
169 pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_2500);
7c12aa08
LT
170}
171
e57f7a3f 172static void xgbe_kx_1000_mode(struct xgbe_prv_data *pdata)
7c12aa08 173{
7c12aa08
LT
174 /* Disable KR training */
175 xgbe_an_disable_kr_training(pdata);
176
177 /* Set MAC to 1G speed */
e57f7a3f
LT
178 pdata->hw_if.set_speed(pdata, SPEED_1000);
179
180 /* Call PHY implementation support to complete rate change */
181 pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_1000);
7c12aa08
LT
182}
183
e57f7a3f 184static enum xgbe_mode xgbe_cur_mode(struct xgbe_prv_data *pdata)
7c12aa08 185{
e57f7a3f 186 return pdata->phy_if.phy_impl.cur_mode(pdata);
7c12aa08
LT
187}
188
189static bool xgbe_in_kr_mode(struct xgbe_prv_data *pdata)
190{
e57f7a3f 191 return (xgbe_cur_mode(pdata) == XGBE_MODE_KR);
7c12aa08
LT
192}
193
e57f7a3f
LT
194static void xgbe_change_mode(struct xgbe_prv_data *pdata,
195 enum xgbe_mode mode)
7c12aa08 196{
e57f7a3f
LT
197 switch (mode) {
198 case XGBE_MODE_KX_1000:
199 xgbe_kx_1000_mode(pdata);
200 break;
201 case XGBE_MODE_KX_2500:
202 xgbe_kx_2500_mode(pdata);
203 break;
204 case XGBE_MODE_KR:
205 xgbe_kr_mode(pdata);
206 break;
207 case XGBE_MODE_UNKNOWN:
208 break;
209 default:
210 netif_dbg(pdata, link, pdata->netdev,
211 "invalid operation mode requested (%u)\n", mode);
7c12aa08
LT
212 }
213}
214
e57f7a3f 215static void xgbe_switch_mode(struct xgbe_prv_data *pdata)
471e14b2 216{
e57f7a3f 217 xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata));
471e14b2
LT
218}
219
e57f7a3f
LT
220static void xgbe_set_mode(struct xgbe_prv_data *pdata,
221 enum xgbe_mode mode)
471e14b2 222{
e57f7a3f
LT
223 if (mode == xgbe_cur_mode(pdata))
224 return;
471e14b2 225
e57f7a3f 226 xgbe_change_mode(pdata, mode);
471e14b2
LT
227}
228
e57f7a3f
LT
229static bool xgbe_use_mode(struct xgbe_prv_data *pdata,
230 enum xgbe_mode mode)
471e14b2 231{
e57f7a3f 232 return pdata->phy_if.phy_impl.use_mode(pdata, mode);
471e14b2
LT
233}
234
7c12aa08
LT
235static void xgbe_set_an(struct xgbe_prv_data *pdata, bool enable, bool restart)
236{
237 unsigned int reg;
238
239 reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1);
240 reg &= ~MDIO_AN_CTRL1_ENABLE;
241
242 if (enable)
243 reg |= MDIO_AN_CTRL1_ENABLE;
244
245 if (restart)
246 reg |= MDIO_AN_CTRL1_RESTART;
247
248 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_CTRL1, reg);
249}
250
251static void xgbe_restart_an(struct xgbe_prv_data *pdata)
252{
253 xgbe_set_an(pdata, true, true);
d5c78399
LT
254
255 netif_dbg(pdata, link, pdata->netdev, "AN enabled/restarted\n");
7c12aa08
LT
256}
257
258static void xgbe_disable_an(struct xgbe_prv_data *pdata)
259{
260 xgbe_set_an(pdata, false, false);
d5c78399
LT
261
262 netif_dbg(pdata, link, pdata->netdev, "AN disabled\n");
7c12aa08
LT
263}
264
265static enum xgbe_an xgbe_an_tx_training(struct xgbe_prv_data *pdata,
266 enum xgbe_rx *state)
267{
268 unsigned int ad_reg, lp_reg, reg;
269
270 *state = XGBE_RX_COMPLETE;
271
272 /* If we're not in KR mode then we're done */
273 if (!xgbe_in_kr_mode(pdata))
274 return XGBE_AN_PAGE_RECEIVED;
275
276 /* Enable/Disable FEC */
277 ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
278 lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
279
280 reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL);
281 reg &= ~(MDIO_PMA_10GBR_FECABLE_ABLE | MDIO_PMA_10GBR_FECABLE_ERRABLE);
282 if ((ad_reg & 0xc000) && (lp_reg & 0xc000))
283 reg |= pdata->fec_ability;
284
285 XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL, reg);
286
287 /* Start KR training */
288 reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
289 if (reg & XGBE_KR_TRAINING_ENABLE) {
e57f7a3f
LT
290 if (pdata->phy_if.phy_impl.kr_training_pre)
291 pdata->phy_if.phy_impl.kr_training_pre(pdata);
7c12aa08
LT
292
293 reg |= XGBE_KR_TRAINING_START;
294 XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL,
295 reg);
296
e57f7a3f
LT
297 if (pdata->phy_if.phy_impl.kr_training_post)
298 pdata->phy_if.phy_impl.kr_training_post(pdata);
d5c78399
LT
299
300 netif_dbg(pdata, link, pdata->netdev,
301 "KR training initiated\n");
7c12aa08
LT
302 }
303
304 return XGBE_AN_PAGE_RECEIVED;
305}
306
307static enum xgbe_an xgbe_an_tx_xnp(struct xgbe_prv_data *pdata,
308 enum xgbe_rx *state)
309{
310 u16 msg;
311
312 *state = XGBE_RX_XNP;
313
314 msg = XGBE_XNP_MCF_NULL_MESSAGE;
315 msg |= XGBE_XNP_MP_FORMATTED;
316
317 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP + 2, 0);
318 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP + 1, 0);
319 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP, msg);
320
321 return XGBE_AN_PAGE_RECEIVED;
322}
323
324static enum xgbe_an xgbe_an_rx_bpa(struct xgbe_prv_data *pdata,
325 enum xgbe_rx *state)
326{
327 unsigned int link_support;
328 unsigned int reg, ad_reg, lp_reg;
329
330 /* Read Base Ability register 2 first */
331 reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
332
333 /* Check for a supported mode, otherwise restart in a different one */
334 link_support = xgbe_in_kr_mode(pdata) ? 0x80 : 0x20;
335 if (!(reg & link_support))
336 return XGBE_AN_INCOMPAT_LINK;
337
338 /* Check Extended Next Page support */
339 ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
340 lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
341
342 return ((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
343 (lp_reg & XGBE_XNP_NP_EXCHANGE))
344 ? xgbe_an_tx_xnp(pdata, state)
345 : xgbe_an_tx_training(pdata, state);
346}
347
348static enum xgbe_an xgbe_an_rx_xnp(struct xgbe_prv_data *pdata,
349 enum xgbe_rx *state)
350{
351 unsigned int ad_reg, lp_reg;
352
353 /* Check Extended Next Page support */
354 ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_XNP);
355 lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPX);
356
357 return ((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
358 (lp_reg & XGBE_XNP_NP_EXCHANGE))
359 ? xgbe_an_tx_xnp(pdata, state)
360 : xgbe_an_tx_training(pdata, state);
361}
362
363static enum xgbe_an xgbe_an_page_received(struct xgbe_prv_data *pdata)
364{
365 enum xgbe_rx *state;
366 unsigned long an_timeout;
367 enum xgbe_an ret;
368
369 if (!pdata->an_start) {
370 pdata->an_start = jiffies;
371 } else {
372 an_timeout = pdata->an_start +
373 msecs_to_jiffies(XGBE_AN_MS_TIMEOUT);
374 if (time_after(jiffies, an_timeout)) {
375 /* Auto-negotiation timed out, reset state */
376 pdata->kr_state = XGBE_RX_BPA;
377 pdata->kx_state = XGBE_RX_BPA;
378
379 pdata->an_start = jiffies;
d5c78399
LT
380
381 netif_dbg(pdata, link, pdata->netdev,
382 "AN timed out, resetting state\n");
7c12aa08
LT
383 }
384 }
385
386 state = xgbe_in_kr_mode(pdata) ? &pdata->kr_state
e57f7a3f 387 : &pdata->kx_state;
7c12aa08
LT
388
389 switch (*state) {
390 case XGBE_RX_BPA:
391 ret = xgbe_an_rx_bpa(pdata, state);
392 break;
393
394 case XGBE_RX_XNP:
395 ret = xgbe_an_rx_xnp(pdata, state);
396 break;
397
398 default:
399 ret = XGBE_AN_ERROR;
400 }
401
402 return ret;
403}
404
405static enum xgbe_an xgbe_an_incompat_link(struct xgbe_prv_data *pdata)
406{
407 /* Be sure we aren't looping trying to negotiate */
408 if (xgbe_in_kr_mode(pdata)) {
409 pdata->kr_state = XGBE_RX_ERROR;
410
411 if (!(pdata->phy.advertising & ADVERTISED_1000baseKX_Full) &&
412 !(pdata->phy.advertising & ADVERTISED_2500baseX_Full))
413 return XGBE_AN_NO_LINK;
414
415 if (pdata->kx_state != XGBE_RX_BPA)
416 return XGBE_AN_NO_LINK;
417 } else {
418 pdata->kx_state = XGBE_RX_ERROR;
419
420 if (!(pdata->phy.advertising & ADVERTISED_10000baseKR_Full))
421 return XGBE_AN_NO_LINK;
422
423 if (pdata->kr_state != XGBE_RX_BPA)
424 return XGBE_AN_NO_LINK;
425 }
426
427 xgbe_disable_an(pdata);
428
429 xgbe_switch_mode(pdata);
430
431 xgbe_restart_an(pdata);
432
433 return XGBE_AN_INCOMPAT_LINK;
434}
435
436static irqreturn_t xgbe_an_isr(int irq, void *data)
437{
438 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
439
d5c78399
LT
440 netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n");
441
ced3fcae
LT
442 /* Disable AN interrupts */
443 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
7c12aa08 444
ced3fcae
LT
445 /* Save the interrupt(s) that fired */
446 pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT);
447
448 if (pdata->an_int) {
449 /* Clear the interrupt(s) that fired and process them */
450 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
451
452 queue_work(pdata->an_workqueue, &pdata->an_irq_work);
453 } else {
454 /* Enable AN interrupts */
455 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK,
456 XGBE_AN_INT_MASK);
457 }
7c12aa08
LT
458
459 return IRQ_HANDLED;
460}
461
462static void xgbe_an_irq_work(struct work_struct *work)
463{
464 struct xgbe_prv_data *pdata = container_of(work,
465 struct xgbe_prv_data,
466 an_irq_work);
467
468 /* Avoid a race between enabling the IRQ and exiting the work by
469 * waiting for the work to finish and then queueing it
470 */
471 flush_work(&pdata->an_work);
472 queue_work(pdata->an_workqueue, &pdata->an_work);
473}
474
d5c78399
LT
475static const char *xgbe_state_as_string(enum xgbe_an state)
476{
477 switch (state) {
478 case XGBE_AN_READY:
479 return "Ready";
480 case XGBE_AN_PAGE_RECEIVED:
481 return "Page-Received";
482 case XGBE_AN_INCOMPAT_LINK:
483 return "Incompatible-Link";
484 case XGBE_AN_COMPLETE:
485 return "Complete";
486 case XGBE_AN_NO_LINK:
487 return "No-Link";
488 case XGBE_AN_ERROR:
489 return "Error";
490 default:
491 return "Undefined";
492 }
493}
494
7c12aa08
LT
495static void xgbe_an_state_machine(struct work_struct *work)
496{
497 struct xgbe_prv_data *pdata = container_of(work,
498 struct xgbe_prv_data,
499 an_work);
500 enum xgbe_an cur_state = pdata->an_state;
7c12aa08
LT
501
502 mutex_lock(&pdata->an_mutex);
503
ced3fcae 504 if (!pdata->an_int)
7c12aa08
LT
505 goto out;
506
507next_int:
ced3fcae 508 if (pdata->an_int & XGBE_AN_PG_RCV) {
7c12aa08 509 pdata->an_state = XGBE_AN_PAGE_RECEIVED;
ced3fcae
LT
510 pdata->an_int &= ~XGBE_AN_PG_RCV;
511 } else if (pdata->an_int & XGBE_AN_INC_LINK) {
7c12aa08 512 pdata->an_state = XGBE_AN_INCOMPAT_LINK;
ced3fcae
LT
513 pdata->an_int &= ~XGBE_AN_INC_LINK;
514 } else if (pdata->an_int & XGBE_AN_INT_CMPLT) {
7c12aa08 515 pdata->an_state = XGBE_AN_COMPLETE;
ced3fcae 516 pdata->an_int &= ~XGBE_AN_INT_CMPLT;
7c12aa08
LT
517 } else {
518 pdata->an_state = XGBE_AN_ERROR;
7c12aa08
LT
519 }
520
7c12aa08
LT
521 pdata->an_result = pdata->an_state;
522
523again:
d5c78399
LT
524 netif_dbg(pdata, link, pdata->netdev, "AN %s\n",
525 xgbe_state_as_string(pdata->an_state));
526
7c12aa08
LT
527 cur_state = pdata->an_state;
528
529 switch (pdata->an_state) {
530 case XGBE_AN_READY:
531 pdata->an_supported = 0;
532 break;
533
534 case XGBE_AN_PAGE_RECEIVED:
535 pdata->an_state = xgbe_an_page_received(pdata);
536 pdata->an_supported++;
537 break;
c5aa9e3b 538
7c12aa08
LT
539 case XGBE_AN_INCOMPAT_LINK:
540 pdata->an_supported = 0;
541 pdata->parallel_detect = 0;
542 pdata->an_state = xgbe_an_incompat_link(pdata);
543 break;
c5aa9e3b 544
7c12aa08
LT
545 case XGBE_AN_COMPLETE:
546 pdata->parallel_detect = pdata->an_supported ? 0 : 1;
d5c78399
LT
547 netif_dbg(pdata, link, pdata->netdev, "%s successful\n",
548 pdata->an_supported ? "Auto negotiation"
549 : "Parallel detection");
7c12aa08
LT
550 break;
551
552 case XGBE_AN_NO_LINK:
553 break;
554
555 default:
556 pdata->an_state = XGBE_AN_ERROR;
557 }
558
559 if (pdata->an_state == XGBE_AN_NO_LINK) {
ced3fcae 560 pdata->an_int = 0;
7c12aa08
LT
561 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
562 } else if (pdata->an_state == XGBE_AN_ERROR) {
563 netdev_err(pdata->netdev,
564 "error during auto-negotiation, state=%u\n",
565 cur_state);
566
ced3fcae 567 pdata->an_int = 0;
7c12aa08
LT
568 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
569 }
570
571 if (pdata->an_state >= XGBE_AN_COMPLETE) {
572 pdata->an_result = pdata->an_state;
573 pdata->an_state = XGBE_AN_READY;
574 pdata->kr_state = XGBE_RX_BPA;
575 pdata->kx_state = XGBE_RX_BPA;
576 pdata->an_start = 0;
d5c78399
LT
577
578 netif_dbg(pdata, link, pdata->netdev, "AN result: %s\n",
579 xgbe_state_as_string(pdata->an_result));
7c12aa08
LT
580 }
581
582 if (cur_state != pdata->an_state)
583 goto again;
584
ced3fcae 585 if (pdata->an_int)
7c12aa08
LT
586 goto next_int;
587
588out:
ced3fcae
LT
589 /* Enable AN interrupts on the way out */
590 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_INT_MASK);
7c12aa08
LT
591
592 mutex_unlock(&pdata->an_mutex);
c5aa9e3b
LT
593}
594
7c12aa08 595static void xgbe_an_init(struct xgbe_prv_data *pdata)
c5aa9e3b 596{
7c12aa08
LT
597 unsigned int reg;
598
599 /* Set up Advertisement register 3 first */
600 reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
601 if (pdata->phy.advertising & ADVERTISED_10000baseR_FEC)
602 reg |= 0xc000;
603 else
604 reg &= ~0xc000;
605
606 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2, reg);
607
608 /* Set up Advertisement register 2 next */
609 reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
610 if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
611 reg |= 0x80;
612 else
613 reg &= ~0x80;
614
615 if ((pdata->phy.advertising & ADVERTISED_1000baseKX_Full) ||
616 (pdata->phy.advertising & ADVERTISED_2500baseX_Full))
617 reg |= 0x20;
618 else
619 reg &= ~0x20;
620
621 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1, reg);
c5aa9e3b 622
7c12aa08
LT
623 /* Set up Advertisement register 1 last */
624 reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
625 if (pdata->phy.advertising & ADVERTISED_Pause)
626 reg |= 0x400;
627 else
628 reg &= ~0x400;
c5aa9e3b 629
7c12aa08
LT
630 if (pdata->phy.advertising & ADVERTISED_Asym_Pause)
631 reg |= 0x800;
632 else
633 reg &= ~0x800;
634
635 /* We don't intend to perform XNP */
636 reg &= ~XGBE_XNP_NP_EXCHANGE;
637
638 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
d5c78399
LT
639
640 netif_dbg(pdata, link, pdata->netdev, "AN initialized\n");
7c12aa08
LT
641}
642
c1ce2f77
LT
643static const char *xgbe_phy_fc_string(struct xgbe_prv_data *pdata)
644{
645 if (pdata->tx_pause && pdata->rx_pause)
646 return "rx/tx";
647 else if (pdata->rx_pause)
648 return "rx";
649 else if (pdata->tx_pause)
650 return "tx";
651 else
652 return "off";
653}
654
7c12aa08
LT
655static const char *xgbe_phy_speed_string(int speed)
656{
657 switch (speed) {
658 case SPEED_1000:
659 return "1Gbps";
660 case SPEED_2500:
661 return "2.5Gbps";
662 case SPEED_10000:
663 return "10Gbps";
664 case SPEED_UNKNOWN:
665 return "Unknown";
666 default:
667 return "Unsupported";
668 }
669}
670
671static void xgbe_phy_print_status(struct xgbe_prv_data *pdata)
672{
673 if (pdata->phy.link)
674 netdev_info(pdata->netdev,
675 "Link is Up - %s/%s - flow control %s\n",
676 xgbe_phy_speed_string(pdata->phy.speed),
677 pdata->phy.duplex == DUPLEX_FULL ? "Full" : "Half",
c1ce2f77 678 xgbe_phy_fc_string(pdata));
7c12aa08
LT
679 else
680 netdev_info(pdata->netdev, "Link is Down\n");
681}
682
683static void xgbe_phy_adjust_link(struct xgbe_prv_data *pdata)
684{
685 int new_state = 0;
686
687 if (pdata->phy.link) {
688 /* Flow control support */
c1ce2f77 689 pdata->pause_autoneg = pdata->phy.pause_autoneg;
7c12aa08 690
c1ce2f77
LT
691 if (pdata->tx_pause != pdata->phy.tx_pause) {
692 new_state = 1;
7c12aa08 693 pdata->hw_if.config_tx_flow_control(pdata);
c1ce2f77 694 pdata->tx_pause = pdata->phy.tx_pause;
7c12aa08
LT
695 }
696
c1ce2f77
LT
697 if (pdata->rx_pause != pdata->phy.rx_pause) {
698 new_state = 1;
7c12aa08 699 pdata->hw_if.config_rx_flow_control(pdata);
c1ce2f77 700 pdata->rx_pause = pdata->phy.rx_pause;
7c12aa08
LT
701 }
702
703 /* Speed support */
704 if (pdata->phy_speed != pdata->phy.speed) {
705 new_state = 1;
706 pdata->phy_speed = pdata->phy.speed;
707 }
708
709 if (pdata->phy_link != pdata->phy.link) {
710 new_state = 1;
711 pdata->phy_link = pdata->phy.link;
712 }
713 } else if (pdata->phy_link) {
714 new_state = 1;
715 pdata->phy_link = 0;
716 pdata->phy_speed = SPEED_UNKNOWN;
717 }
718
719 if (new_state && netif_msg_link(pdata))
720 xgbe_phy_print_status(pdata);
721}
722
e57f7a3f
LT
723static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
724{
725 return pdata->phy_if.phy_impl.valid_speed(pdata, speed);
726}
727
7c12aa08
LT
728static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata)
729{
e57f7a3f
LT
730 enum xgbe_mode mode;
731
d5c78399
LT
732 netif_dbg(pdata, link, pdata->netdev, "fixed PHY configuration\n");
733
7c12aa08
LT
734 /* Disable auto-negotiation */
735 xgbe_disable_an(pdata);
736
e57f7a3f
LT
737 /* Set specified mode for specified speed */
738 mode = pdata->phy_if.phy_impl.get_mode(pdata, pdata->phy.speed);
739 switch (mode) {
740 case XGBE_MODE_KX_1000:
741 case XGBE_MODE_KX_2500:
742 case XGBE_MODE_KR:
7c12aa08 743 break;
e57f7a3f 744 case XGBE_MODE_UNKNOWN:
7c12aa08
LT
745 default:
746 return -EINVAL;
747 }
c5aa9e3b 748
7c12aa08
LT
749 /* Validate duplex mode */
750 if (pdata->phy.duplex != DUPLEX_FULL)
751 return -EINVAL;
752
e57f7a3f
LT
753 xgbe_set_mode(pdata, mode);
754
c5aa9e3b
LT
755 return 0;
756}
757
7c12aa08
LT
758static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata)
759{
760 set_bit(XGBE_LINK_INIT, &pdata->dev_state);
761 pdata->link_check = jiffies;
762
763 if (pdata->phy.autoneg != AUTONEG_ENABLE)
764 return xgbe_phy_config_fixed(pdata);
765
d5c78399
LT
766 netif_dbg(pdata, link, pdata->netdev, "AN PHY configuration\n");
767
7c12aa08
LT
768 /* Disable auto-negotiation interrupt */
769 disable_irq(pdata->an_irq);
770
771 /* Start auto-negotiation in a supported mode */
e57f7a3f 772 if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
7c12aa08 773 xgbe_set_mode(pdata, XGBE_MODE_KR);
e57f7a3f
LT
774 } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
775 xgbe_set_mode(pdata, XGBE_MODE_KX_2500);
776 } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
777 xgbe_set_mode(pdata, XGBE_MODE_KX_1000);
7c12aa08
LT
778 } else {
779 enable_irq(pdata->an_irq);
780 return -EINVAL;
781 }
782
783 /* Disable and stop any in progress auto-negotiation */
784 xgbe_disable_an(pdata);
785
786 /* Clear any auto-negotitation interrupts */
787 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
788
789 pdata->an_result = XGBE_AN_READY;
790 pdata->an_state = XGBE_AN_READY;
791 pdata->kr_state = XGBE_RX_BPA;
792 pdata->kx_state = XGBE_RX_BPA;
793
794 /* Re-enable auto-negotiation interrupt */
795 enable_irq(pdata->an_irq);
796
797 /* Set up advertisement registers based on current settings */
798 xgbe_an_init(pdata);
799
800 /* Enable and start auto-negotiation */
801 xgbe_restart_an(pdata);
802
803 return 0;
804}
805
806static int xgbe_phy_config_aneg(struct xgbe_prv_data *pdata)
807{
808 int ret;
809
810 mutex_lock(&pdata->an_mutex);
811
812 ret = __xgbe_phy_config_aneg(pdata);
813 if (ret)
814 set_bit(XGBE_LINK_ERR, &pdata->dev_state);
815 else
816 clear_bit(XGBE_LINK_ERR, &pdata->dev_state);
817
818 mutex_unlock(&pdata->an_mutex);
819
820 return ret;
821}
822
823static bool xgbe_phy_aneg_done(struct xgbe_prv_data *pdata)
824{
825 return (pdata->an_result == XGBE_AN_COMPLETE);
826}
827
828static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
829{
830 unsigned long link_timeout;
831
832 link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ);
d5c78399
LT
833 if (time_after(jiffies, link_timeout)) {
834 netif_dbg(pdata, link, pdata->netdev, "AN link timeout\n");
7c12aa08 835 xgbe_phy_config_aneg(pdata);
d5c78399 836 }
7c12aa08
LT
837}
838
e57f7a3f 839static enum xgbe_mode xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
7c12aa08 840{
e57f7a3f 841 return pdata->phy_if.phy_impl.an_outcome(pdata);
7c12aa08
LT
842}
843
e57f7a3f 844static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
7c12aa08 845{
e57f7a3f 846 enum xgbe_mode mode;
7c12aa08
LT
847
848 pdata->phy.lp_advertising = 0;
849
850 if ((pdata->phy.autoneg != AUTONEG_ENABLE) || pdata->parallel_detect)
e57f7a3f
LT
851 mode = xgbe_cur_mode(pdata);
852 else
853 mode = xgbe_phy_status_aneg(pdata);
7c12aa08 854
e57f7a3f
LT
855 switch (mode) {
856 case XGBE_MODE_KX_1000:
857 pdata->phy.speed = SPEED_1000;
858 break;
859 case XGBE_MODE_KX_2500:
860 pdata->phy.speed = SPEED_2500;
861 break;
862 case XGBE_MODE_KR:
7c12aa08 863 pdata->phy.speed = SPEED_10000;
e57f7a3f
LT
864 break;
865 case XGBE_MODE_UNKNOWN:
866 default:
7c12aa08
LT
867 pdata->phy.speed = SPEED_UNKNOWN;
868 }
869
7c12aa08 870 pdata->phy.duplex = DUPLEX_FULL;
e57f7a3f
LT
871
872 xgbe_set_mode(pdata, mode);
7c12aa08
LT
873}
874
875static void xgbe_phy_status(struct xgbe_prv_data *pdata)
876{
e57f7a3f 877 unsigned int link_aneg;
7c12aa08
LT
878
879 if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) {
50789845 880 netif_carrier_off(pdata->netdev);
7c12aa08
LT
881
882 pdata->phy.link = 0;
883 goto adjust_link;
884 }
885
886 link_aneg = (pdata->phy.autoneg == AUTONEG_ENABLE);
887
e57f7a3f 888 pdata->phy.link = pdata->phy_if.phy_impl.link_status(pdata);
7c12aa08
LT
889 if (pdata->phy.link) {
890 if (link_aneg && !xgbe_phy_aneg_done(pdata)) {
891 xgbe_check_link_timeout(pdata);
892 return;
893 }
894
e57f7a3f 895 xgbe_phy_status_result(pdata);
7c12aa08
LT
896
897 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
898 clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
899
50789845 900 netif_carrier_on(pdata->netdev);
7c12aa08
LT
901 } else {
902 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) {
903 xgbe_check_link_timeout(pdata);
904
905 if (link_aneg)
906 return;
907 }
908
e57f7a3f 909 xgbe_phy_status_result(pdata);
7c12aa08 910
50789845 911 netif_carrier_off(pdata->netdev);
7c12aa08
LT
912 }
913
914adjust_link:
915 xgbe_phy_adjust_link(pdata);
916}
917
918static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
919{
d5c78399
LT
920 netif_dbg(pdata, link, pdata->netdev, "stopping PHY\n");
921
e57f7a3f
LT
922 if (!pdata->phy_started)
923 return;
924
925 /* Indicate the PHY is down */
926 pdata->phy_started = 0;
927
7c12aa08
LT
928 /* Disable auto-negotiation */
929 xgbe_disable_an(pdata);
930
931 /* Disable auto-negotiation interrupts */
932 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
933
934 devm_free_irq(pdata->dev, pdata->an_irq, pdata);
935
e57f7a3f
LT
936 pdata->phy_if.phy_impl.stop(pdata);
937
7c12aa08 938 pdata->phy.link = 0;
50789845 939 netif_carrier_off(pdata->netdev);
7c12aa08
LT
940
941 xgbe_phy_adjust_link(pdata);
942}
943
944static int xgbe_phy_start(struct xgbe_prv_data *pdata)
945{
946 struct net_device *netdev = pdata->netdev;
947 int ret;
948
d5c78399
LT
949 netif_dbg(pdata, link, pdata->netdev, "starting PHY\n");
950
e57f7a3f
LT
951 ret = pdata->phy_if.phy_impl.start(pdata);
952 if (ret)
953 return ret;
954
7c12aa08
LT
955 ret = devm_request_irq(pdata->dev, pdata->an_irq,
956 xgbe_an_isr, 0, pdata->an_name,
957 pdata);
958 if (ret) {
959 netdev_err(netdev, "phy irq request failed\n");
e57f7a3f 960 goto err_stop;
7c12aa08
LT
961 }
962
963 /* Set initial mode - call the mode setting routines
964 * directly to insure we are properly configured
965 */
e57f7a3f
LT
966 if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
967 xgbe_kr_mode(pdata);
968 } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
969 xgbe_kx_2500_mode(pdata);
970 } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
971 xgbe_kx_1000_mode(pdata);
7c12aa08
LT
972 } else {
973 ret = -EINVAL;
974 goto err_irq;
975 }
976
e57f7a3f
LT
977 /* Indicate the PHY is up and running */
978 pdata->phy_started = 1;
979
7c12aa08
LT
980 /* Set up advertisement registers based on current settings */
981 xgbe_an_init(pdata);
982
983 /* Enable auto-negotiation interrupts */
984 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0x07);
985
986 return xgbe_phy_config_aneg(pdata);
987
988err_irq:
989 devm_free_irq(pdata->dev, pdata->an_irq, pdata);
990
e57f7a3f
LT
991err_stop:
992 pdata->phy_if.phy_impl.stop(pdata);
993
7c12aa08
LT
994 return ret;
995}
996
997static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
998{
e57f7a3f 999 int ret;
7c12aa08 1000
e57f7a3f
LT
1001 ret = pdata->phy_if.phy_impl.reset(pdata);
1002 if (ret)
1003 return ret;
7c12aa08
LT
1004
1005 /* Disable auto-negotiation for now */
1006 xgbe_disable_an(pdata);
1007
1008 /* Clear auto-negotiation interrupts */
1009 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
1010
1011 return 0;
1012}
1013
1014static void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata)
c5aa9e3b
LT
1015{
1016 struct device *dev = pdata->dev;
c5aa9e3b 1017
34bf65df
LT
1018 dev_dbg(dev, "\n************* PHY Reg dump **********************\n");
1019
d9682c90 1020 dev_dbg(dev, "PCS Control Reg (%#06x) = %#06x\n", MDIO_CTRL1,
34bf65df 1021 XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1));
d9682c90 1022 dev_dbg(dev, "PCS Status Reg (%#06x) = %#06x\n", MDIO_STAT1,
34bf65df 1023 XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1));
d9682c90 1024 dev_dbg(dev, "Phy Id (PHYS ID 1 %#06x)= %#06x\n", MDIO_DEVID1,
34bf65df 1025 XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVID1));
d9682c90 1026 dev_dbg(dev, "Phy Id (PHYS ID 2 %#06x)= %#06x\n", MDIO_DEVID2,
34bf65df 1027 XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVID2));
d9682c90 1028 dev_dbg(dev, "Devices in Package (%#06x)= %#06x\n", MDIO_DEVS1,
34bf65df 1029 XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVS1));
d9682c90 1030 dev_dbg(dev, "Devices in Package (%#06x)= %#06x\n", MDIO_DEVS2,
34bf65df
LT
1031 XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVS2));
1032
d9682c90 1033 dev_dbg(dev, "Auto-Neg Control Reg (%#06x) = %#06x\n", MDIO_CTRL1,
34bf65df 1034 XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1));
d9682c90 1035 dev_dbg(dev, "Auto-Neg Status Reg (%#06x) = %#06x\n", MDIO_STAT1,
34bf65df 1036 XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_STAT1));
d9682c90 1037 dev_dbg(dev, "Auto-Neg Ad Reg 1 (%#06x) = %#06x\n",
34bf65df
LT
1038 MDIO_AN_ADVERTISE,
1039 XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE));
d9682c90 1040 dev_dbg(dev, "Auto-Neg Ad Reg 2 (%#06x) = %#06x\n",
34bf65df
LT
1041 MDIO_AN_ADVERTISE + 1,
1042 XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1));
d9682c90 1043 dev_dbg(dev, "Auto-Neg Ad Reg 3 (%#06x) = %#06x\n",
34bf65df
LT
1044 MDIO_AN_ADVERTISE + 2,
1045 XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2));
d9682c90 1046 dev_dbg(dev, "Auto-Neg Completion Reg (%#06x) = %#06x\n",
34bf65df
LT
1047 MDIO_AN_COMP_STAT,
1048 XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_COMP_STAT));
1049
34bf65df 1050 dev_dbg(dev, "\n*************************************************\n");
c5aa9e3b
LT
1051}
1052
e57f7a3f
LT
1053static int xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata)
1054{
1055 if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
1056 return SPEED_10000;
1057 else if (pdata->phy.advertising & ADVERTISED_2500baseX_Full)
1058 return SPEED_2500;
1059 else if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full)
1060 return SPEED_1000;
1061
1062 return SPEED_UNKNOWN;
1063}
1064
1065static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
c5aa9e3b 1066{
e57f7a3f
LT
1067 xgbe_phy_stop(pdata);
1068
1069 pdata->phy_if.phy_impl.exit(pdata);
1070}
1071
1072static int xgbe_phy_init(struct xgbe_prv_data *pdata)
1073{
1074 int ret;
1075
7c12aa08
LT
1076 mutex_init(&pdata->an_mutex);
1077 INIT_WORK(&pdata->an_irq_work, xgbe_an_irq_work);
1078 INIT_WORK(&pdata->an_work, xgbe_an_state_machine);
1079 pdata->mdio_mmd = MDIO_MMD_PCS;
c5aa9e3b 1080
e57f7a3f 1081 /* Check for FEC support */
7c12aa08
LT
1082 pdata->fec_ability = XMDIO_READ(pdata, MDIO_MMD_PMAPMD,
1083 MDIO_PMA_10GBR_FECABLE);
1084 pdata->fec_ability &= (MDIO_PMA_10GBR_FECABLE_ABLE |
1085 MDIO_PMA_10GBR_FECABLE_ERRABLE);
c5aa9e3b 1086
e57f7a3f
LT
1087 /* Setup the phy (including supported features) */
1088 ret = pdata->phy_if.phy_impl.init(pdata);
1089 if (ret)
1090 return ret;
7c12aa08 1091 pdata->phy.advertising = pdata->phy.supported;
c5aa9e3b 1092
7c12aa08 1093 pdata->phy.address = 0;
c5aa9e3b 1094
e57f7a3f
LT
1095 if (pdata->phy.advertising & ADVERTISED_Autoneg) {
1096 pdata->phy.autoneg = AUTONEG_ENABLE;
1097 pdata->phy.speed = SPEED_UNKNOWN;
1098 pdata->phy.duplex = DUPLEX_UNKNOWN;
1099 } else {
1100 pdata->phy.autoneg = AUTONEG_DISABLE;
1101 pdata->phy.speed = xgbe_phy_best_advertised_speed(pdata);
1102 pdata->phy.duplex = DUPLEX_FULL;
1103 }
c5aa9e3b 1104
7c12aa08 1105 pdata->phy.link = 0;
c5aa9e3b 1106
c1ce2f77
LT
1107 pdata->phy.pause_autoneg = pdata->pause_autoneg;
1108 pdata->phy.tx_pause = pdata->tx_pause;
1109 pdata->phy.rx_pause = pdata->rx_pause;
1110
1111 /* Fix up Flow Control advertising */
1112 pdata->phy.advertising &= ~ADVERTISED_Pause;
1113 pdata->phy.advertising &= ~ADVERTISED_Asym_Pause;
1114
1115 if (pdata->rx_pause) {
1116 pdata->phy.advertising |= ADVERTISED_Pause;
1117 pdata->phy.advertising |= ADVERTISED_Asym_Pause;
1118 }
1119
1120 if (pdata->tx_pause)
1121 pdata->phy.advertising ^= ADVERTISED_Asym_Pause;
1122
34bf65df
LT
1123 if (netif_msg_drv(pdata))
1124 xgbe_dump_phy_registers(pdata);
e57f7a3f
LT
1125
1126 return 0;
c5aa9e3b
LT
1127}
1128
7c12aa08 1129void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *phy_if)
c5aa9e3b 1130{
7c12aa08 1131 phy_if->phy_init = xgbe_phy_init;
e57f7a3f 1132 phy_if->phy_exit = xgbe_phy_exit;
c5aa9e3b 1133
7c12aa08
LT
1134 phy_if->phy_reset = xgbe_phy_reset;
1135 phy_if->phy_start = xgbe_phy_start;
1136 phy_if->phy_stop = xgbe_phy_stop;
c5aa9e3b 1137
7c12aa08
LT
1138 phy_if->phy_status = xgbe_phy_status;
1139 phy_if->phy_config_aneg = xgbe_phy_config_aneg;
e57f7a3f
LT
1140
1141 phy_if->phy_valid_speed = xgbe_phy_valid_speed;
c5aa9e3b 1142}