]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
amd-xgbe: Prepare for introduction of clause 37 autoneg
[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
a64def41
LT
128static void xgbe_an73_clear_interrupts(struct xgbe_prv_data *pdata)
129{
130 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
131}
132
133static void xgbe_an73_disable_interrupts(struct xgbe_prv_data *pdata)
134{
135 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
136}
137
138static void xgbe_an73_enable_interrupts(struct xgbe_prv_data *pdata)
139{
140 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_CL73_INT_MASK);
141}
142
143static void xgbe_an_enable_interrupts(struct xgbe_prv_data *pdata)
144{
145 switch (pdata->an_mode) {
146 case XGBE_AN_MODE_CL73:
147 xgbe_an73_enable_interrupts(pdata);
148 break;
149 default:
150 break;
151 }
152}
153
154static void xgbe_an73_enable_kr_training(struct xgbe_prv_data *pdata)
c5aa9e3b 155{
7c12aa08 156 unsigned int reg;
c5aa9e3b 157
7c12aa08 158 reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
c5aa9e3b 159
7c12aa08
LT
160 reg |= XGBE_KR_TRAINING_ENABLE;
161 XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
162}
163
a64def41 164static void xgbe_an73_disable_kr_training(struct xgbe_prv_data *pdata)
7c12aa08
LT
165{
166 unsigned int reg;
167
168 reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
169
170 reg &= ~XGBE_KR_TRAINING_ENABLE;
171 XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
172}
173
e57f7a3f 174static void xgbe_kr_mode(struct xgbe_prv_data *pdata)
7c12aa08 175{
7c12aa08 176 /* Enable KR training */
a64def41 177 xgbe_an73_enable_kr_training(pdata);
7c12aa08
LT
178
179 /* Set MAC to 10G speed */
e57f7a3f
LT
180 pdata->hw_if.set_speed(pdata, SPEED_10000);
181
182 /* Call PHY implementation support to complete rate change */
183 pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KR);
7c12aa08
LT
184}
185
e57f7a3f 186static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata)
7c12aa08 187{
7c12aa08 188 /* Disable KR training */
a64def41 189 xgbe_an73_disable_kr_training(pdata);
7c12aa08
LT
190
191 /* Set MAC to 2.5G speed */
e57f7a3f
LT
192 pdata->hw_if.set_speed(pdata, SPEED_2500);
193
194 /* Call PHY implementation support to complete rate change */
195 pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_2500);
7c12aa08
LT
196}
197
e57f7a3f 198static void xgbe_kx_1000_mode(struct xgbe_prv_data *pdata)
7c12aa08 199{
7c12aa08 200 /* Disable KR training */
a64def41 201 xgbe_an73_disable_kr_training(pdata);
7c12aa08
LT
202
203 /* Set MAC to 1G speed */
e57f7a3f
LT
204 pdata->hw_if.set_speed(pdata, SPEED_1000);
205
206 /* Call PHY implementation support to complete rate change */
207 pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_1000);
7c12aa08
LT
208}
209
e57f7a3f 210static enum xgbe_mode xgbe_cur_mode(struct xgbe_prv_data *pdata)
7c12aa08 211{
e57f7a3f 212 return pdata->phy_if.phy_impl.cur_mode(pdata);
7c12aa08
LT
213}
214
215static bool xgbe_in_kr_mode(struct xgbe_prv_data *pdata)
216{
e57f7a3f 217 return (xgbe_cur_mode(pdata) == XGBE_MODE_KR);
7c12aa08
LT
218}
219
e57f7a3f
LT
220static void xgbe_change_mode(struct xgbe_prv_data *pdata,
221 enum xgbe_mode mode)
7c12aa08 222{
e57f7a3f
LT
223 switch (mode) {
224 case XGBE_MODE_KX_1000:
225 xgbe_kx_1000_mode(pdata);
226 break;
227 case XGBE_MODE_KX_2500:
228 xgbe_kx_2500_mode(pdata);
229 break;
230 case XGBE_MODE_KR:
231 xgbe_kr_mode(pdata);
232 break;
233 case XGBE_MODE_UNKNOWN:
234 break;
235 default:
236 netif_dbg(pdata, link, pdata->netdev,
237 "invalid operation mode requested (%u)\n", mode);
7c12aa08
LT
238 }
239}
240
e57f7a3f 241static void xgbe_switch_mode(struct xgbe_prv_data *pdata)
471e14b2 242{
e57f7a3f 243 xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata));
471e14b2
LT
244}
245
e57f7a3f
LT
246static void xgbe_set_mode(struct xgbe_prv_data *pdata,
247 enum xgbe_mode mode)
471e14b2 248{
e57f7a3f
LT
249 if (mode == xgbe_cur_mode(pdata))
250 return;
471e14b2 251
e57f7a3f 252 xgbe_change_mode(pdata, mode);
471e14b2
LT
253}
254
e57f7a3f
LT
255static bool xgbe_use_mode(struct xgbe_prv_data *pdata,
256 enum xgbe_mode mode)
471e14b2 257{
e57f7a3f 258 return pdata->phy_if.phy_impl.use_mode(pdata, mode);
471e14b2
LT
259}
260
a64def41
LT
261static void xgbe_an73_set(struct xgbe_prv_data *pdata, bool enable,
262 bool restart)
7c12aa08
LT
263{
264 unsigned int reg;
265
266 reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1);
267 reg &= ~MDIO_AN_CTRL1_ENABLE;
268
269 if (enable)
270 reg |= MDIO_AN_CTRL1_ENABLE;
271
272 if (restart)
273 reg |= MDIO_AN_CTRL1_RESTART;
274
275 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_CTRL1, reg);
276}
277
a64def41 278static void xgbe_an73_restart(struct xgbe_prv_data *pdata)
7c12aa08 279{
a64def41
LT
280 xgbe_an73_enable_interrupts(pdata);
281 xgbe_an73_set(pdata, true, true);
d5c78399 282
a64def41 283 netif_dbg(pdata, link, pdata->netdev, "CL73 AN enabled/restarted\n");
7c12aa08
LT
284}
285
a64def41 286static void xgbe_an73_disable(struct xgbe_prv_data *pdata)
7c12aa08 287{
a64def41
LT
288 xgbe_an73_set(pdata, false, false);
289 xgbe_an73_disable_interrupts(pdata);
d5c78399 290
a64def41 291 netif_dbg(pdata, link, pdata->netdev, "CL73 AN disabled\n");
7c12aa08
LT
292}
293
a64def41
LT
294static void xgbe_an_restart(struct xgbe_prv_data *pdata)
295{
296 switch (pdata->an_mode) {
297 case XGBE_AN_MODE_CL73:
298 xgbe_an73_restart(pdata);
299 break;
300 default:
301 break;
302 }
303}
304
305static void xgbe_an_disable(struct xgbe_prv_data *pdata)
306{
307 switch (pdata->an_mode) {
308 case XGBE_AN_MODE_CL73:
309 xgbe_an73_disable(pdata);
310 break;
311 default:
312 break;
313 }
314}
315
316static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata,
317 enum xgbe_rx *state)
7c12aa08
LT
318{
319 unsigned int ad_reg, lp_reg, reg;
320
321 *state = XGBE_RX_COMPLETE;
322
323 /* If we're not in KR mode then we're done */
324 if (!xgbe_in_kr_mode(pdata))
325 return XGBE_AN_PAGE_RECEIVED;
326
327 /* Enable/Disable FEC */
328 ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
329 lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
330
331 reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL);
332 reg &= ~(MDIO_PMA_10GBR_FECABLE_ABLE | MDIO_PMA_10GBR_FECABLE_ERRABLE);
333 if ((ad_reg & 0xc000) && (lp_reg & 0xc000))
334 reg |= pdata->fec_ability;
335
336 XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_FECCTRL, reg);
337
338 /* Start KR training */
339 reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
340 if (reg & XGBE_KR_TRAINING_ENABLE) {
e57f7a3f
LT
341 if (pdata->phy_if.phy_impl.kr_training_pre)
342 pdata->phy_if.phy_impl.kr_training_pre(pdata);
7c12aa08
LT
343
344 reg |= XGBE_KR_TRAINING_START;
345 XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL,
346 reg);
347
e57f7a3f
LT
348 if (pdata->phy_if.phy_impl.kr_training_post)
349 pdata->phy_if.phy_impl.kr_training_post(pdata);
d5c78399
LT
350
351 netif_dbg(pdata, link, pdata->netdev,
352 "KR training initiated\n");
7c12aa08
LT
353 }
354
355 return XGBE_AN_PAGE_RECEIVED;
356}
357
a64def41
LT
358static enum xgbe_an xgbe_an73_tx_xnp(struct xgbe_prv_data *pdata,
359 enum xgbe_rx *state)
7c12aa08
LT
360{
361 u16 msg;
362
363 *state = XGBE_RX_XNP;
364
365 msg = XGBE_XNP_MCF_NULL_MESSAGE;
366 msg |= XGBE_XNP_MP_FORMATTED;
367
368 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP + 2, 0);
369 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP + 1, 0);
370 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_XNP, msg);
371
372 return XGBE_AN_PAGE_RECEIVED;
373}
374
a64def41
LT
375static enum xgbe_an xgbe_an73_rx_bpa(struct xgbe_prv_data *pdata,
376 enum xgbe_rx *state)
7c12aa08
LT
377{
378 unsigned int link_support;
379 unsigned int reg, ad_reg, lp_reg;
380
381 /* Read Base Ability register 2 first */
382 reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
383
384 /* Check for a supported mode, otherwise restart in a different one */
385 link_support = xgbe_in_kr_mode(pdata) ? 0x80 : 0x20;
386 if (!(reg & link_support))
387 return XGBE_AN_INCOMPAT_LINK;
388
389 /* Check Extended Next Page support */
390 ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
391 lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
392
393 return ((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
394 (lp_reg & XGBE_XNP_NP_EXCHANGE))
a64def41
LT
395 ? xgbe_an73_tx_xnp(pdata, state)
396 : xgbe_an73_tx_training(pdata, state);
7c12aa08
LT
397}
398
a64def41
LT
399static enum xgbe_an xgbe_an73_rx_xnp(struct xgbe_prv_data *pdata,
400 enum xgbe_rx *state)
7c12aa08
LT
401{
402 unsigned int ad_reg, lp_reg;
403
404 /* Check Extended Next Page support */
405 ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_XNP);
406 lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPX);
407
408 return ((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
409 (lp_reg & XGBE_XNP_NP_EXCHANGE))
a64def41
LT
410 ? xgbe_an73_tx_xnp(pdata, state)
411 : xgbe_an73_tx_training(pdata, state);
7c12aa08
LT
412}
413
a64def41 414static enum xgbe_an xgbe_an73_page_received(struct xgbe_prv_data *pdata)
7c12aa08
LT
415{
416 enum xgbe_rx *state;
417 unsigned long an_timeout;
418 enum xgbe_an ret;
419
420 if (!pdata->an_start) {
421 pdata->an_start = jiffies;
422 } else {
423 an_timeout = pdata->an_start +
424 msecs_to_jiffies(XGBE_AN_MS_TIMEOUT);
425 if (time_after(jiffies, an_timeout)) {
426 /* Auto-negotiation timed out, reset state */
427 pdata->kr_state = XGBE_RX_BPA;
428 pdata->kx_state = XGBE_RX_BPA;
429
430 pdata->an_start = jiffies;
d5c78399
LT
431
432 netif_dbg(pdata, link, pdata->netdev,
a64def41 433 "CL73 AN timed out, resetting state\n");
7c12aa08
LT
434 }
435 }
436
437 state = xgbe_in_kr_mode(pdata) ? &pdata->kr_state
e57f7a3f 438 : &pdata->kx_state;
7c12aa08
LT
439
440 switch (*state) {
441 case XGBE_RX_BPA:
a64def41 442 ret = xgbe_an73_rx_bpa(pdata, state);
7c12aa08
LT
443 break;
444
445 case XGBE_RX_XNP:
a64def41 446 ret = xgbe_an73_rx_xnp(pdata, state);
7c12aa08
LT
447 break;
448
449 default:
450 ret = XGBE_AN_ERROR;
451 }
452
453 return ret;
454}
455
a64def41 456static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
7c12aa08
LT
457{
458 /* Be sure we aren't looping trying to negotiate */
459 if (xgbe_in_kr_mode(pdata)) {
460 pdata->kr_state = XGBE_RX_ERROR;
461
462 if (!(pdata->phy.advertising & ADVERTISED_1000baseKX_Full) &&
463 !(pdata->phy.advertising & ADVERTISED_2500baseX_Full))
464 return XGBE_AN_NO_LINK;
465
466 if (pdata->kx_state != XGBE_RX_BPA)
467 return XGBE_AN_NO_LINK;
468 } else {
469 pdata->kx_state = XGBE_RX_ERROR;
470
471 if (!(pdata->phy.advertising & ADVERTISED_10000baseKR_Full))
472 return XGBE_AN_NO_LINK;
473
474 if (pdata->kr_state != XGBE_RX_BPA)
475 return XGBE_AN_NO_LINK;
476 }
477
a64def41 478 xgbe_an73_disable(pdata);
7c12aa08
LT
479
480 xgbe_switch_mode(pdata);
481
a64def41 482 xgbe_an73_restart(pdata);
7c12aa08
LT
483
484 return XGBE_AN_INCOMPAT_LINK;
485}
486
a64def41 487static void xgbe_an73_isr(struct xgbe_prv_data *pdata)
7c12aa08 488{
ced3fcae 489 /* Disable AN interrupts */
a64def41 490 xgbe_an73_disable_interrupts(pdata);
7c12aa08 491
ced3fcae
LT
492 /* Save the interrupt(s) that fired */
493 pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT);
494
495 if (pdata->an_int) {
496 /* Clear the interrupt(s) that fired and process them */
497 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, ~pdata->an_int);
498
499 queue_work(pdata->an_workqueue, &pdata->an_irq_work);
500 } else {
501 /* Enable AN interrupts */
a64def41
LT
502 xgbe_an73_enable_interrupts(pdata);
503 }
504}
505
506static irqreturn_t xgbe_an_isr(int irq, void *data)
507{
508 struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
509
510 netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n");
511
512 switch (pdata->an_mode) {
513 case XGBE_AN_MODE_CL73:
514 xgbe_an73_isr(pdata);
515 break;
516 default:
517 break;
ced3fcae 518 }
7c12aa08
LT
519
520 return IRQ_HANDLED;
521}
522
523static void xgbe_an_irq_work(struct work_struct *work)
524{
525 struct xgbe_prv_data *pdata = container_of(work,
526 struct xgbe_prv_data,
527 an_irq_work);
528
529 /* Avoid a race between enabling the IRQ and exiting the work by
530 * waiting for the work to finish and then queueing it
531 */
532 flush_work(&pdata->an_work);
533 queue_work(pdata->an_workqueue, &pdata->an_work);
534}
535
d5c78399
LT
536static const char *xgbe_state_as_string(enum xgbe_an state)
537{
538 switch (state) {
539 case XGBE_AN_READY:
540 return "Ready";
541 case XGBE_AN_PAGE_RECEIVED:
542 return "Page-Received";
543 case XGBE_AN_INCOMPAT_LINK:
544 return "Incompatible-Link";
545 case XGBE_AN_COMPLETE:
546 return "Complete";
547 case XGBE_AN_NO_LINK:
548 return "No-Link";
549 case XGBE_AN_ERROR:
550 return "Error";
551 default:
552 return "Undefined";
553 }
554}
555
a64def41 556static void xgbe_an73_state_machine(struct xgbe_prv_data *pdata)
7c12aa08 557{
7c12aa08 558 enum xgbe_an cur_state = pdata->an_state;
7c12aa08 559
ced3fcae 560 if (!pdata->an_int)
a64def41 561 return;
7c12aa08
LT
562
563next_int:
a64def41 564 if (pdata->an_int & XGBE_AN_CL73_PG_RCV) {
7c12aa08 565 pdata->an_state = XGBE_AN_PAGE_RECEIVED;
a64def41
LT
566 pdata->an_int &= ~XGBE_AN_CL73_PG_RCV;
567 } else if (pdata->an_int & XGBE_AN_CL73_INC_LINK) {
7c12aa08 568 pdata->an_state = XGBE_AN_INCOMPAT_LINK;
a64def41
LT
569 pdata->an_int &= ~XGBE_AN_CL73_INC_LINK;
570 } else if (pdata->an_int & XGBE_AN_CL73_INT_CMPLT) {
7c12aa08 571 pdata->an_state = XGBE_AN_COMPLETE;
a64def41 572 pdata->an_int &= ~XGBE_AN_CL73_INT_CMPLT;
7c12aa08
LT
573 } else {
574 pdata->an_state = XGBE_AN_ERROR;
7c12aa08
LT
575 }
576
7c12aa08
LT
577 pdata->an_result = pdata->an_state;
578
579again:
a64def41 580 netif_dbg(pdata, link, pdata->netdev, "CL73 AN %s\n",
d5c78399
LT
581 xgbe_state_as_string(pdata->an_state));
582
7c12aa08
LT
583 cur_state = pdata->an_state;
584
585 switch (pdata->an_state) {
586 case XGBE_AN_READY:
587 pdata->an_supported = 0;
588 break;
589
590 case XGBE_AN_PAGE_RECEIVED:
a64def41 591 pdata->an_state = xgbe_an73_page_received(pdata);
7c12aa08
LT
592 pdata->an_supported++;
593 break;
c5aa9e3b 594
7c12aa08
LT
595 case XGBE_AN_INCOMPAT_LINK:
596 pdata->an_supported = 0;
597 pdata->parallel_detect = 0;
a64def41 598 pdata->an_state = xgbe_an73_incompat_link(pdata);
7c12aa08 599 break;
c5aa9e3b 600
7c12aa08
LT
601 case XGBE_AN_COMPLETE:
602 pdata->parallel_detect = pdata->an_supported ? 0 : 1;
d5c78399
LT
603 netif_dbg(pdata, link, pdata->netdev, "%s successful\n",
604 pdata->an_supported ? "Auto negotiation"
605 : "Parallel detection");
7c12aa08
LT
606 break;
607
608 case XGBE_AN_NO_LINK:
609 break;
610
611 default:
612 pdata->an_state = XGBE_AN_ERROR;
613 }
614
615 if (pdata->an_state == XGBE_AN_NO_LINK) {
ced3fcae 616 pdata->an_int = 0;
a64def41 617 xgbe_an73_clear_interrupts(pdata);
7c12aa08
LT
618 } else if (pdata->an_state == XGBE_AN_ERROR) {
619 netdev_err(pdata->netdev,
620 "error during auto-negotiation, state=%u\n",
621 cur_state);
622
ced3fcae 623 pdata->an_int = 0;
a64def41 624 xgbe_an73_clear_interrupts(pdata);
7c12aa08
LT
625 }
626
627 if (pdata->an_state >= XGBE_AN_COMPLETE) {
628 pdata->an_result = pdata->an_state;
629 pdata->an_state = XGBE_AN_READY;
630 pdata->kr_state = XGBE_RX_BPA;
631 pdata->kx_state = XGBE_RX_BPA;
632 pdata->an_start = 0;
d5c78399 633
a64def41 634 netif_dbg(pdata, link, pdata->netdev, "CL73 AN result: %s\n",
d5c78399 635 xgbe_state_as_string(pdata->an_result));
7c12aa08
LT
636 }
637
638 if (cur_state != pdata->an_state)
639 goto again;
640
ced3fcae 641 if (pdata->an_int)
7c12aa08
LT
642 goto next_int;
643
a64def41
LT
644 xgbe_an73_enable_interrupts(pdata);
645}
646
647static void xgbe_an_state_machine(struct work_struct *work)
648{
649 struct xgbe_prv_data *pdata = container_of(work,
650 struct xgbe_prv_data,
651 an_work);
652
653 mutex_lock(&pdata->an_mutex);
654
655 switch (pdata->an_mode) {
656 case XGBE_AN_MODE_CL73:
657 xgbe_an73_state_machine(pdata);
658 break;
659 default:
660 break;
661 }
7c12aa08
LT
662
663 mutex_unlock(&pdata->an_mutex);
c5aa9e3b
LT
664}
665
a64def41 666static void xgbe_an73_init(struct xgbe_prv_data *pdata)
c5aa9e3b 667{
7c12aa08
LT
668 unsigned int reg;
669
670 /* Set up Advertisement register 3 first */
671 reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
672 if (pdata->phy.advertising & ADVERTISED_10000baseR_FEC)
673 reg |= 0xc000;
674 else
675 reg &= ~0xc000;
676
677 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2, reg);
678
679 /* Set up Advertisement register 2 next */
680 reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
681 if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
682 reg |= 0x80;
683 else
684 reg &= ~0x80;
685
686 if ((pdata->phy.advertising & ADVERTISED_1000baseKX_Full) ||
687 (pdata->phy.advertising & ADVERTISED_2500baseX_Full))
688 reg |= 0x20;
689 else
690 reg &= ~0x20;
691
692 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1, reg);
c5aa9e3b 693
7c12aa08
LT
694 /* Set up Advertisement register 1 last */
695 reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
696 if (pdata->phy.advertising & ADVERTISED_Pause)
697 reg |= 0x400;
698 else
699 reg &= ~0x400;
c5aa9e3b 700
7c12aa08
LT
701 if (pdata->phy.advertising & ADVERTISED_Asym_Pause)
702 reg |= 0x800;
703 else
704 reg &= ~0x800;
705
706 /* We don't intend to perform XNP */
707 reg &= ~XGBE_XNP_NP_EXCHANGE;
708
709 XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
d5c78399 710
a64def41
LT
711 netif_dbg(pdata, link, pdata->netdev, "CL73 AN initialized\n");
712}
713
714static void xgbe_an_init(struct xgbe_prv_data *pdata)
715{
716 /* Set up advertisement registers based on current settings */
717 pdata->an_mode = pdata->phy_if.phy_impl.an_mode(pdata);
718 switch (pdata->an_mode) {
719 case XGBE_AN_MODE_CL73:
720 xgbe_an73_init(pdata);
721 break;
722 default:
723 break;
724 }
7c12aa08
LT
725}
726
c1ce2f77
LT
727static const char *xgbe_phy_fc_string(struct xgbe_prv_data *pdata)
728{
729 if (pdata->tx_pause && pdata->rx_pause)
730 return "rx/tx";
731 else if (pdata->rx_pause)
732 return "rx";
733 else if (pdata->tx_pause)
734 return "tx";
735 else
736 return "off";
737}
738
7c12aa08
LT
739static const char *xgbe_phy_speed_string(int speed)
740{
741 switch (speed) {
742 case SPEED_1000:
743 return "1Gbps";
744 case SPEED_2500:
745 return "2.5Gbps";
746 case SPEED_10000:
747 return "10Gbps";
748 case SPEED_UNKNOWN:
749 return "Unknown";
750 default:
751 return "Unsupported";
752 }
753}
754
755static void xgbe_phy_print_status(struct xgbe_prv_data *pdata)
756{
757 if (pdata->phy.link)
758 netdev_info(pdata->netdev,
759 "Link is Up - %s/%s - flow control %s\n",
760 xgbe_phy_speed_string(pdata->phy.speed),
761 pdata->phy.duplex == DUPLEX_FULL ? "Full" : "Half",
c1ce2f77 762 xgbe_phy_fc_string(pdata));
7c12aa08
LT
763 else
764 netdev_info(pdata->netdev, "Link is Down\n");
765}
766
767static void xgbe_phy_adjust_link(struct xgbe_prv_data *pdata)
768{
769 int new_state = 0;
770
771 if (pdata->phy.link) {
772 /* Flow control support */
c1ce2f77 773 pdata->pause_autoneg = pdata->phy.pause_autoneg;
7c12aa08 774
c1ce2f77
LT
775 if (pdata->tx_pause != pdata->phy.tx_pause) {
776 new_state = 1;
7c12aa08 777 pdata->hw_if.config_tx_flow_control(pdata);
c1ce2f77 778 pdata->tx_pause = pdata->phy.tx_pause;
7c12aa08
LT
779 }
780
c1ce2f77
LT
781 if (pdata->rx_pause != pdata->phy.rx_pause) {
782 new_state = 1;
7c12aa08 783 pdata->hw_if.config_rx_flow_control(pdata);
c1ce2f77 784 pdata->rx_pause = pdata->phy.rx_pause;
7c12aa08
LT
785 }
786
787 /* Speed support */
788 if (pdata->phy_speed != pdata->phy.speed) {
789 new_state = 1;
790 pdata->phy_speed = pdata->phy.speed;
791 }
792
793 if (pdata->phy_link != pdata->phy.link) {
794 new_state = 1;
795 pdata->phy_link = pdata->phy.link;
796 }
797 } else if (pdata->phy_link) {
798 new_state = 1;
799 pdata->phy_link = 0;
800 pdata->phy_speed = SPEED_UNKNOWN;
801 }
802
803 if (new_state && netif_msg_link(pdata))
804 xgbe_phy_print_status(pdata);
805}
806
e57f7a3f
LT
807static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
808{
809 return pdata->phy_if.phy_impl.valid_speed(pdata, speed);
810}
811
7c12aa08
LT
812static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata)
813{
e57f7a3f
LT
814 enum xgbe_mode mode;
815
d5c78399
LT
816 netif_dbg(pdata, link, pdata->netdev, "fixed PHY configuration\n");
817
7c12aa08 818 /* Disable auto-negotiation */
a64def41 819 xgbe_an_disable(pdata);
7c12aa08 820
e57f7a3f
LT
821 /* Set specified mode for specified speed */
822 mode = pdata->phy_if.phy_impl.get_mode(pdata, pdata->phy.speed);
823 switch (mode) {
824 case XGBE_MODE_KX_1000:
825 case XGBE_MODE_KX_2500:
826 case XGBE_MODE_KR:
7c12aa08 827 break;
e57f7a3f 828 case XGBE_MODE_UNKNOWN:
7c12aa08
LT
829 default:
830 return -EINVAL;
831 }
c5aa9e3b 832
7c12aa08
LT
833 /* Validate duplex mode */
834 if (pdata->phy.duplex != DUPLEX_FULL)
835 return -EINVAL;
836
e57f7a3f
LT
837 xgbe_set_mode(pdata, mode);
838
c5aa9e3b
LT
839 return 0;
840}
841
7c12aa08
LT
842static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata)
843{
844 set_bit(XGBE_LINK_INIT, &pdata->dev_state);
845 pdata->link_check = jiffies;
846
847 if (pdata->phy.autoneg != AUTONEG_ENABLE)
848 return xgbe_phy_config_fixed(pdata);
849
d5c78399
LT
850 netif_dbg(pdata, link, pdata->netdev, "AN PHY configuration\n");
851
7c12aa08
LT
852 /* Disable auto-negotiation interrupt */
853 disable_irq(pdata->an_irq);
854
855 /* Start auto-negotiation in a supported mode */
e57f7a3f 856 if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
7c12aa08 857 xgbe_set_mode(pdata, XGBE_MODE_KR);
e57f7a3f
LT
858 } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
859 xgbe_set_mode(pdata, XGBE_MODE_KX_2500);
860 } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
861 xgbe_set_mode(pdata, XGBE_MODE_KX_1000);
7c12aa08
LT
862 } else {
863 enable_irq(pdata->an_irq);
864 return -EINVAL;
865 }
866
867 /* Disable and stop any in progress auto-negotiation */
a64def41 868 xgbe_an_disable(pdata);
7c12aa08
LT
869
870 /* Clear any auto-negotitation interrupts */
a64def41 871 xgbe_an73_clear_interrupts(pdata);
7c12aa08
LT
872
873 pdata->an_result = XGBE_AN_READY;
874 pdata->an_state = XGBE_AN_READY;
875 pdata->kr_state = XGBE_RX_BPA;
876 pdata->kx_state = XGBE_RX_BPA;
877
878 /* Re-enable auto-negotiation interrupt */
879 enable_irq(pdata->an_irq);
880
7c12aa08 881 xgbe_an_init(pdata);
a64def41 882 xgbe_an_restart(pdata);
7c12aa08
LT
883
884 return 0;
885}
886
887static int xgbe_phy_config_aneg(struct xgbe_prv_data *pdata)
888{
889 int ret;
890
891 mutex_lock(&pdata->an_mutex);
892
893 ret = __xgbe_phy_config_aneg(pdata);
894 if (ret)
895 set_bit(XGBE_LINK_ERR, &pdata->dev_state);
896 else
897 clear_bit(XGBE_LINK_ERR, &pdata->dev_state);
898
899 mutex_unlock(&pdata->an_mutex);
900
901 return ret;
902}
903
904static bool xgbe_phy_aneg_done(struct xgbe_prv_data *pdata)
905{
906 return (pdata->an_result == XGBE_AN_COMPLETE);
907}
908
909static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
910{
911 unsigned long link_timeout;
912
913 link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ);
d5c78399
LT
914 if (time_after(jiffies, link_timeout)) {
915 netif_dbg(pdata, link, pdata->netdev, "AN link timeout\n");
7c12aa08 916 xgbe_phy_config_aneg(pdata);
d5c78399 917 }
7c12aa08
LT
918}
919
e57f7a3f 920static enum xgbe_mode xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
7c12aa08 921{
e57f7a3f 922 return pdata->phy_if.phy_impl.an_outcome(pdata);
7c12aa08
LT
923}
924
e57f7a3f 925static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
7c12aa08 926{
e57f7a3f 927 enum xgbe_mode mode;
7c12aa08
LT
928
929 pdata->phy.lp_advertising = 0;
930
931 if ((pdata->phy.autoneg != AUTONEG_ENABLE) || pdata->parallel_detect)
e57f7a3f
LT
932 mode = xgbe_cur_mode(pdata);
933 else
934 mode = xgbe_phy_status_aneg(pdata);
7c12aa08 935
e57f7a3f
LT
936 switch (mode) {
937 case XGBE_MODE_KX_1000:
938 pdata->phy.speed = SPEED_1000;
939 break;
940 case XGBE_MODE_KX_2500:
941 pdata->phy.speed = SPEED_2500;
942 break;
943 case XGBE_MODE_KR:
7c12aa08 944 pdata->phy.speed = SPEED_10000;
e57f7a3f
LT
945 break;
946 case XGBE_MODE_UNKNOWN:
947 default:
7c12aa08
LT
948 pdata->phy.speed = SPEED_UNKNOWN;
949 }
950
7c12aa08 951 pdata->phy.duplex = DUPLEX_FULL;
e57f7a3f
LT
952
953 xgbe_set_mode(pdata, mode);
7c12aa08
LT
954}
955
956static void xgbe_phy_status(struct xgbe_prv_data *pdata)
957{
e57f7a3f 958 unsigned int link_aneg;
7c12aa08
LT
959
960 if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) {
50789845 961 netif_carrier_off(pdata->netdev);
7c12aa08
LT
962
963 pdata->phy.link = 0;
964 goto adjust_link;
965 }
966
967 link_aneg = (pdata->phy.autoneg == AUTONEG_ENABLE);
968
e57f7a3f 969 pdata->phy.link = pdata->phy_if.phy_impl.link_status(pdata);
7c12aa08
LT
970 if (pdata->phy.link) {
971 if (link_aneg && !xgbe_phy_aneg_done(pdata)) {
972 xgbe_check_link_timeout(pdata);
973 return;
974 }
975
e57f7a3f 976 xgbe_phy_status_result(pdata);
7c12aa08
LT
977
978 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
979 clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
980
50789845 981 netif_carrier_on(pdata->netdev);
7c12aa08
LT
982 } else {
983 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) {
984 xgbe_check_link_timeout(pdata);
985
986 if (link_aneg)
987 return;
988 }
989
e57f7a3f 990 xgbe_phy_status_result(pdata);
7c12aa08 991
50789845 992 netif_carrier_off(pdata->netdev);
7c12aa08
LT
993 }
994
995adjust_link:
996 xgbe_phy_adjust_link(pdata);
997}
998
999static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
1000{
d5c78399
LT
1001 netif_dbg(pdata, link, pdata->netdev, "stopping PHY\n");
1002
e57f7a3f
LT
1003 if (!pdata->phy_started)
1004 return;
1005
1006 /* Indicate the PHY is down */
1007 pdata->phy_started = 0;
1008
7c12aa08 1009 /* Disable auto-negotiation */
a64def41 1010 xgbe_an_disable(pdata);
7c12aa08
LT
1011
1012 devm_free_irq(pdata->dev, pdata->an_irq, pdata);
1013
e57f7a3f
LT
1014 pdata->phy_if.phy_impl.stop(pdata);
1015
7c12aa08 1016 pdata->phy.link = 0;
50789845 1017 netif_carrier_off(pdata->netdev);
7c12aa08
LT
1018
1019 xgbe_phy_adjust_link(pdata);
1020}
1021
1022static int xgbe_phy_start(struct xgbe_prv_data *pdata)
1023{
1024 struct net_device *netdev = pdata->netdev;
1025 int ret;
1026
d5c78399
LT
1027 netif_dbg(pdata, link, pdata->netdev, "starting PHY\n");
1028
e57f7a3f
LT
1029 ret = pdata->phy_if.phy_impl.start(pdata);
1030 if (ret)
1031 return ret;
1032
7c12aa08
LT
1033 ret = devm_request_irq(pdata->dev, pdata->an_irq,
1034 xgbe_an_isr, 0, pdata->an_name,
1035 pdata);
1036 if (ret) {
1037 netdev_err(netdev, "phy irq request failed\n");
e57f7a3f 1038 goto err_stop;
7c12aa08
LT
1039 }
1040
1041 /* Set initial mode - call the mode setting routines
1042 * directly to insure we are properly configured
1043 */
e57f7a3f
LT
1044 if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
1045 xgbe_kr_mode(pdata);
1046 } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
1047 xgbe_kx_2500_mode(pdata);
1048 } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
1049 xgbe_kx_1000_mode(pdata);
7c12aa08
LT
1050 } else {
1051 ret = -EINVAL;
1052 goto err_irq;
1053 }
1054
e57f7a3f
LT
1055 /* Indicate the PHY is up and running */
1056 pdata->phy_started = 1;
1057
7c12aa08 1058 xgbe_an_init(pdata);
a64def41 1059 xgbe_an_enable_interrupts(pdata);
7c12aa08
LT
1060
1061 return xgbe_phy_config_aneg(pdata);
1062
1063err_irq:
1064 devm_free_irq(pdata->dev, pdata->an_irq, pdata);
1065
e57f7a3f
LT
1066err_stop:
1067 pdata->phy_if.phy_impl.stop(pdata);
1068
7c12aa08
LT
1069 return ret;
1070}
1071
1072static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
1073{
e57f7a3f 1074 int ret;
7c12aa08 1075
e57f7a3f
LT
1076 ret = pdata->phy_if.phy_impl.reset(pdata);
1077 if (ret)
1078 return ret;
7c12aa08
LT
1079
1080 /* Disable auto-negotiation for now */
a64def41 1081 xgbe_an_disable(pdata);
7c12aa08
LT
1082
1083 /* Clear auto-negotiation interrupts */
a64def41 1084 xgbe_an73_clear_interrupts(pdata);
7c12aa08
LT
1085
1086 return 0;
1087}
1088
1089static void xgbe_dump_phy_registers(struct xgbe_prv_data *pdata)
c5aa9e3b
LT
1090{
1091 struct device *dev = pdata->dev;
c5aa9e3b 1092
34bf65df
LT
1093 dev_dbg(dev, "\n************* PHY Reg dump **********************\n");
1094
d9682c90 1095 dev_dbg(dev, "PCS Control Reg (%#06x) = %#06x\n", MDIO_CTRL1,
34bf65df 1096 XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1));
d9682c90 1097 dev_dbg(dev, "PCS Status Reg (%#06x) = %#06x\n", MDIO_STAT1,
34bf65df 1098 XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1));
d9682c90 1099 dev_dbg(dev, "Phy Id (PHYS ID 1 %#06x)= %#06x\n", MDIO_DEVID1,
34bf65df 1100 XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVID1));
d9682c90 1101 dev_dbg(dev, "Phy Id (PHYS ID 2 %#06x)= %#06x\n", MDIO_DEVID2,
34bf65df 1102 XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVID2));
d9682c90 1103 dev_dbg(dev, "Devices in Package (%#06x)= %#06x\n", MDIO_DEVS1,
34bf65df 1104 XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVS1));
d9682c90 1105 dev_dbg(dev, "Devices in Package (%#06x)= %#06x\n", MDIO_DEVS2,
34bf65df
LT
1106 XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVS2));
1107
d9682c90 1108 dev_dbg(dev, "Auto-Neg Control Reg (%#06x) = %#06x\n", MDIO_CTRL1,
34bf65df 1109 XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1));
d9682c90 1110 dev_dbg(dev, "Auto-Neg Status Reg (%#06x) = %#06x\n", MDIO_STAT1,
34bf65df 1111 XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_STAT1));
d9682c90 1112 dev_dbg(dev, "Auto-Neg Ad Reg 1 (%#06x) = %#06x\n",
34bf65df
LT
1113 MDIO_AN_ADVERTISE,
1114 XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE));
d9682c90 1115 dev_dbg(dev, "Auto-Neg Ad Reg 2 (%#06x) = %#06x\n",
34bf65df
LT
1116 MDIO_AN_ADVERTISE + 1,
1117 XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1));
d9682c90 1118 dev_dbg(dev, "Auto-Neg Ad Reg 3 (%#06x) = %#06x\n",
34bf65df
LT
1119 MDIO_AN_ADVERTISE + 2,
1120 XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2));
d9682c90 1121 dev_dbg(dev, "Auto-Neg Completion Reg (%#06x) = %#06x\n",
34bf65df
LT
1122 MDIO_AN_COMP_STAT,
1123 XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_COMP_STAT));
1124
34bf65df 1125 dev_dbg(dev, "\n*************************************************\n");
c5aa9e3b
LT
1126}
1127
e57f7a3f
LT
1128static int xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata)
1129{
1130 if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
1131 return SPEED_10000;
1132 else if (pdata->phy.advertising & ADVERTISED_2500baseX_Full)
1133 return SPEED_2500;
1134 else if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full)
1135 return SPEED_1000;
1136
1137 return SPEED_UNKNOWN;
1138}
1139
1140static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
c5aa9e3b 1141{
e57f7a3f
LT
1142 xgbe_phy_stop(pdata);
1143
1144 pdata->phy_if.phy_impl.exit(pdata);
1145}
1146
1147static int xgbe_phy_init(struct xgbe_prv_data *pdata)
1148{
1149 int ret;
1150
7c12aa08
LT
1151 mutex_init(&pdata->an_mutex);
1152 INIT_WORK(&pdata->an_irq_work, xgbe_an_irq_work);
1153 INIT_WORK(&pdata->an_work, xgbe_an_state_machine);
1154 pdata->mdio_mmd = MDIO_MMD_PCS;
c5aa9e3b 1155
e57f7a3f 1156 /* Check for FEC support */
7c12aa08
LT
1157 pdata->fec_ability = XMDIO_READ(pdata, MDIO_MMD_PMAPMD,
1158 MDIO_PMA_10GBR_FECABLE);
1159 pdata->fec_ability &= (MDIO_PMA_10GBR_FECABLE_ABLE |
1160 MDIO_PMA_10GBR_FECABLE_ERRABLE);
c5aa9e3b 1161
e57f7a3f
LT
1162 /* Setup the phy (including supported features) */
1163 ret = pdata->phy_if.phy_impl.init(pdata);
1164 if (ret)
1165 return ret;
7c12aa08 1166 pdata->phy.advertising = pdata->phy.supported;
c5aa9e3b 1167
7c12aa08 1168 pdata->phy.address = 0;
c5aa9e3b 1169
e57f7a3f
LT
1170 if (pdata->phy.advertising & ADVERTISED_Autoneg) {
1171 pdata->phy.autoneg = AUTONEG_ENABLE;
1172 pdata->phy.speed = SPEED_UNKNOWN;
1173 pdata->phy.duplex = DUPLEX_UNKNOWN;
1174 } else {
1175 pdata->phy.autoneg = AUTONEG_DISABLE;
1176 pdata->phy.speed = xgbe_phy_best_advertised_speed(pdata);
1177 pdata->phy.duplex = DUPLEX_FULL;
1178 }
c5aa9e3b 1179
7c12aa08 1180 pdata->phy.link = 0;
c5aa9e3b 1181
c1ce2f77
LT
1182 pdata->phy.pause_autoneg = pdata->pause_autoneg;
1183 pdata->phy.tx_pause = pdata->tx_pause;
1184 pdata->phy.rx_pause = pdata->rx_pause;
1185
1186 /* Fix up Flow Control advertising */
1187 pdata->phy.advertising &= ~ADVERTISED_Pause;
1188 pdata->phy.advertising &= ~ADVERTISED_Asym_Pause;
1189
1190 if (pdata->rx_pause) {
1191 pdata->phy.advertising |= ADVERTISED_Pause;
1192 pdata->phy.advertising |= ADVERTISED_Asym_Pause;
1193 }
1194
1195 if (pdata->tx_pause)
1196 pdata->phy.advertising ^= ADVERTISED_Asym_Pause;
1197
34bf65df
LT
1198 if (netif_msg_drv(pdata))
1199 xgbe_dump_phy_registers(pdata);
e57f7a3f
LT
1200
1201 return 0;
c5aa9e3b
LT
1202}
1203
7c12aa08 1204void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *phy_if)
c5aa9e3b 1205{
7c12aa08 1206 phy_if->phy_init = xgbe_phy_init;
e57f7a3f 1207 phy_if->phy_exit = xgbe_phy_exit;
c5aa9e3b 1208
7c12aa08
LT
1209 phy_if->phy_reset = xgbe_phy_reset;
1210 phy_if->phy_start = xgbe_phy_start;
1211 phy_if->phy_stop = xgbe_phy_stop;
c5aa9e3b 1212
7c12aa08
LT
1213 phy_if->phy_status = xgbe_phy_status;
1214 phy_if->phy_config_aneg = xgbe_phy_config_aneg;
e57f7a3f
LT
1215
1216 phy_if->phy_valid_speed = xgbe_phy_valid_speed;
c5aa9e3b 1217}