]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/axgbe/xgbe-phy-v1.c
MFV r366990: less v563.
[FreeBSD/FreeBSD.git] / sys / dev / axgbe / xgbe-phy-v1.c
1 /*
2  * AMD 10Gb Ethernet driver
3  *
4  * Copyright (c) 2020 Advanced Micro Devices, Inc.
5  *
6  * This file is available to you under your choice of the following two
7  * licenses:
8  *
9  * License 1: GPLv2
10  *
11  * This file is free software; you may copy, redistribute and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 2 of the License, or (at
14  * your option) any later version.
15  *
16  * This file is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  *
24  * This file incorporates work covered by the following copyright and
25  * permission notice:
26  *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
27  *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
28  *     Inc. unless otherwise expressly agreed to in writing between Synopsys
29  *     and you.
30  *
31  *     The Software IS NOT an item of Licensed Software or Licensed Product
32  *     under any End User Software License Agreement or Agreement for Licensed
33  *     Product with Synopsys or any supplement thereto.  Permission is hereby
34  *     granted, free of charge, to any person obtaining a copy of this software
35  *     annotated with this license and the Software, to deal in the Software
36  *     without restriction, including without limitation the rights to use,
37  *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
38  *     of the Software, and to permit persons to whom the Software is furnished
39  *     to do so, subject to the following conditions:
40  *
41  *     The above copyright notice and this permission notice shall be included
42  *     in all copies or substantial portions of the Software.
43  *
44  *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
45  *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
46  *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
47  *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
48  *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
49  *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
50  *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
51  *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53  *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
54  *     THE POSSIBILITY OF SUCH DAMAGE.
55  *
56  *
57  * License 2: Modified BSD
58  *
59  * Redistribution and use in source and binary forms, with or without
60  * modification, are permitted provided that the following conditions are met:
61  *     * Redistributions of source code must retain the above copyright
62  *       notice, this list of conditions and the following disclaimer.
63  *     * Redistributions in binary form must reproduce the above copyright
64  *       notice, this list of conditions and the following disclaimer in the
65  *       documentation and/or other materials provided with the distribution.
66  *     * Neither the name of Advanced Micro Devices, Inc. nor the
67  *       names of its contributors may be used to endorse or promote products
68  *       derived from this software without specific prior written permission.
69  *
70  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
71  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
72  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
73  * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
74  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
75  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
76  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
77  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
78  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
79  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
80  *
81  * This file incorporates work covered by the following copyright and
82  * permission notice:
83  *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
84  *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
85  *     Inc. unless otherwise expressly agreed to in writing between Synopsys
86  *     and you.
87  *
88  *     The Software IS NOT an item of Licensed Software or Licensed Product
89  *     under any End User Software License Agreement or Agreement for Licensed
90  *     Product with Synopsys or any supplement thereto.  Permission is hereby
91  *     granted, free of charge, to any person obtaining a copy of this software
92  *     annotated with this license and the Software, to deal in the Software
93  *     without restriction, including without limitation the rights to use,
94  *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
95  *     of the Software, and to permit persons to whom the Software is furnished
96  *     to do so, subject to the following conditions:
97  *
98  *     The above copyright notice and this permission notice shall be included
99  *     in all copies or substantial portions of the Software.
100  *
101  *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
102  *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
103  *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
104  *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
105  *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
106  *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
107  *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
108  *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
109  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
110  *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
111  *     THE POSSIBILITY OF SUCH DAMAGE.
112  */
113
114 #include <sys/cdefs.h>
115 __FBSDID("$FreeBSD$");
116
117 #include "xgbe.h"
118 #include "xgbe-common.h"
119
120 struct xgbe_phy_data {
121         /* 1000/10000 vs 2500/10000 indicator */
122         unsigned int speed_set;
123
124         /* SerDes UEFI configurable settings.
125          *   Switching between modes/speeds requires new values for some
126          *   SerDes settings.  The values can be supplied as device
127          *   properties in array format.  The first array entry is for
128          *   1GbE, second for 2.5GbE and third for 10GbE
129          */
130         uint32_t blwc[XGBE_SPEEDS];
131         uint32_t cdr_rate[XGBE_SPEEDS];
132         uint32_t pq_skew[XGBE_SPEEDS];
133         uint32_t tx_amp[XGBE_SPEEDS];
134         uint32_t dfe_tap_cfg[XGBE_SPEEDS];
135         uint32_t dfe_tap_ena[XGBE_SPEEDS];
136 };
137
138 static void
139 xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata)
140 {
141         XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
142 }
143
144 static void
145 xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata)
146 {
147         XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
148 }
149
150 static enum xgbe_mode
151 xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
152 {
153         struct xgbe_phy_data *phy_data = pdata->phy_data;
154         enum xgbe_mode mode;
155         unsigned int ad_reg, lp_reg;
156
157         XGBE_SET_LP_ADV(&pdata->phy, Autoneg);
158         XGBE_SET_LP_ADV(&pdata->phy, Backplane);
159
160         /* Compare Advertisement and Link Partner register 1 */
161         ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
162         lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
163         if (lp_reg & 0x400)
164                 XGBE_SET_LP_ADV(&pdata->phy, Pause);
165         if (lp_reg & 0x800)
166                 XGBE_SET_LP_ADV(&pdata->phy, Asym_Pause);
167
168         axgbe_printf(1, "%s: pause_autoneg %d ad_reg 0x%x lp_reg 0x%x\n",
169             __func__, pdata->phy.pause_autoneg, ad_reg, lp_reg);
170
171         if (pdata->phy.pause_autoneg) {
172                 /* Set flow control based on auto-negotiation result */
173                 pdata->phy.tx_pause = 0;
174                 pdata->phy.rx_pause = 0;
175
176                 if (ad_reg & lp_reg & 0x400) {
177                         pdata->phy.tx_pause = 1;
178                         pdata->phy.rx_pause = 1;
179                 } else if (ad_reg & lp_reg & 0x800) {
180                         if (ad_reg & 0x400)
181                                 pdata->phy.rx_pause = 1;
182                         else if (lp_reg & 0x400)
183                                 pdata->phy.tx_pause = 1;
184                 }
185         }
186
187         /* Compare Advertisement and Link Partner register 2 */
188         ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
189         lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
190         if (lp_reg & 0x80)
191                 XGBE_SET_LP_ADV(&pdata->phy, 10000baseKR_Full);
192         if (lp_reg & 0x20) {
193                 if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
194                         XGBE_SET_LP_ADV(&pdata->phy, 2500baseX_Full);
195                 else
196                         XGBE_SET_LP_ADV(&pdata->phy, 1000baseKX_Full);
197         }
198
199         ad_reg &= lp_reg;
200         if (ad_reg & 0x80) {
201                 pdata->phy.speed = SPEED_10000;
202                 mode = XGBE_MODE_KR;
203         } else if (ad_reg & 0x20) {
204                 switch (pdata->speed_set) {
205                 case XGBE_SPEEDSET_1000_10000:
206                         pdata->phy.speed = SPEED_1000;
207                         mode = XGBE_MODE_KX_1000;
208                         break;
209
210                 case XGBE_SPEEDSET_2500_10000:
211                         pdata->phy.speed = SPEED_2500;
212                         mode = XGBE_MODE_KX_2500;
213                         break;
214                 }
215         } else {
216                 mode = XGBE_MODE_UNKNOWN;
217                 pdata->phy.speed = SPEED_UNKNOWN;
218         }
219
220         /* Compare Advertisement and Link Partner register 3 */
221         ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
222         lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
223         if (lp_reg & 0xc000)
224                 XGBE_SET_LP_ADV(&pdata->phy, 10000baseR_FEC);
225
226         return (mode);
227 }
228
229 static void
230 xgbe_phy_an_advertising(struct xgbe_prv_data *pdata, struct xgbe_phy *dphy)
231 {
232         XGBE_LM_COPY(dphy, advertising, &pdata->phy, advertising);
233 }
234
235 static int
236 xgbe_phy_an_config(struct xgbe_prv_data *pdata)
237 {
238         /* Nothing uniquely required for an configuration */
239         return (0);
240 }
241
242 static enum xgbe_an_mode
243 xgbe_phy_an_mode(struct xgbe_prv_data *pdata)
244 {
245         return (XGBE_AN_MODE_CL73);
246 }
247
248 static void
249 xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata)
250 {
251         unsigned int reg;
252
253         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
254
255         reg |= MDIO_CTRL1_LPOWER;
256         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
257
258         DELAY(75);
259
260         reg &= ~MDIO_CTRL1_LPOWER;
261         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
262 }
263
264 static void
265 xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)
266 {
267         /* Assert Rx and Tx ratechange */
268         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
269 }
270
271 static void
272 xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)
273 {
274         unsigned int wait;
275         uint16_t status;
276
277         /* Release Rx and Tx ratechange */
278         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
279
280         /* Wait for Rx and Tx ready */
281         wait = XGBE_RATECHANGE_COUNT;
282         while (wait--) {
283                 DELAY(50);
284
285                 status = XSIR0_IOREAD(pdata, SIR0_STATUS);
286                 if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
287                     XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
288                         goto rx_reset;
289         }
290
291         axgbe_printf(2, "SerDes rx/tx not ready (%#hx)\n", status);
292
293 rx_reset:
294         /* Perform Rx reset for the DFE changes */
295         XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
296         XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
297 }
298
299 static void
300 xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)
301 {
302         struct xgbe_phy_data *phy_data = pdata->phy_data;
303         unsigned int reg;
304
305         /* Set PCS to KR/10G speed */
306         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
307         reg &= ~MDIO_PCS_CTRL2_TYPE;
308         reg |= MDIO_PCS_CTRL2_10GBR;
309         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
310
311         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
312         reg &= ~MDIO_CTRL1_SPEEDSEL;
313         reg |= MDIO_CTRL1_SPEED10G;
314         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
315
316         xgbe_phy_pcs_power_cycle(pdata);
317
318         /* Set SerDes to 10G speed */
319         xgbe_phy_start_ratechange(pdata);
320
321         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
322         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
323         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
324
325         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
326                            phy_data->cdr_rate[XGBE_SPEED_10000]);
327         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
328                            phy_data->tx_amp[XGBE_SPEED_10000]);
329         XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
330                            phy_data->blwc[XGBE_SPEED_10000]);
331         XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
332                            phy_data->pq_skew[XGBE_SPEED_10000]);
333         XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
334                            phy_data->dfe_tap_cfg[XGBE_SPEED_10000]);
335         XRXTX_IOWRITE(pdata, RXTX_REG22,
336                       phy_data->dfe_tap_ena[XGBE_SPEED_10000]);
337
338         xgbe_phy_complete_ratechange(pdata);
339
340         axgbe_printf(2, "10GbE KR mode set\n");
341 }
342
343 static void
344 xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata)
345 {
346         struct xgbe_phy_data *phy_data = pdata->phy_data;
347         unsigned int reg;
348
349         /* Set PCS to KX/1G speed */
350         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
351         reg &= ~MDIO_PCS_CTRL2_TYPE;
352         reg |= MDIO_PCS_CTRL2_10GBX;
353         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
354
355         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
356         reg &= ~MDIO_CTRL1_SPEEDSEL;
357         reg |= MDIO_CTRL1_SPEED1G;
358         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
359
360         xgbe_phy_pcs_power_cycle(pdata);
361
362         /* Set SerDes to 2.5G speed */
363         xgbe_phy_start_ratechange(pdata);
364
365         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
366         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
367         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
368
369         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
370                            phy_data->cdr_rate[XGBE_SPEED_2500]);
371         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
372                            phy_data->tx_amp[XGBE_SPEED_2500]);
373         XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
374                            phy_data->blwc[XGBE_SPEED_2500]);
375         XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
376                            phy_data->pq_skew[XGBE_SPEED_2500]);
377         XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
378                            phy_data->dfe_tap_cfg[XGBE_SPEED_2500]);
379         XRXTX_IOWRITE(pdata, RXTX_REG22,
380                       phy_data->dfe_tap_ena[XGBE_SPEED_2500]);
381
382         xgbe_phy_complete_ratechange(pdata);
383
384         axgbe_printf(2, "2.5GbE KX mode set\n");
385 }
386
387 static void
388 xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata)
389 {
390         struct xgbe_phy_data *phy_data = pdata->phy_data;
391         unsigned int reg;
392
393         /* Set PCS to KX/1G speed */
394         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
395         reg &= ~MDIO_PCS_CTRL2_TYPE;
396         reg |= MDIO_PCS_CTRL2_10GBX;
397         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
398
399         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
400         reg &= ~MDIO_CTRL1_SPEEDSEL;
401         reg |= MDIO_CTRL1_SPEED1G;
402         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
403
404         xgbe_phy_pcs_power_cycle(pdata);
405
406         /* Set SerDes to 1G speed */
407         xgbe_phy_start_ratechange(pdata);
408
409         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
410         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
411         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
412
413         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
414                            phy_data->cdr_rate[XGBE_SPEED_1000]);
415         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
416                            phy_data->tx_amp[XGBE_SPEED_1000]);
417         XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
418                            phy_data->blwc[XGBE_SPEED_1000]);
419         XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
420                            phy_data->pq_skew[XGBE_SPEED_1000]);
421         XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
422                            phy_data->dfe_tap_cfg[XGBE_SPEED_1000]);
423         XRXTX_IOWRITE(pdata, RXTX_REG22,
424                       phy_data->dfe_tap_ena[XGBE_SPEED_1000]);
425
426         xgbe_phy_complete_ratechange(pdata);
427
428         axgbe_printf(2, "1GbE KX mode set\n");
429 }
430
431 static enum xgbe_mode
432 xgbe_phy_cur_mode(struct xgbe_prv_data *pdata)
433 {
434         struct xgbe_phy_data *phy_data = pdata->phy_data;
435         enum xgbe_mode mode;
436         unsigned int reg;
437
438         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
439         reg &= MDIO_PCS_CTRL2_TYPE;
440
441         if (reg == MDIO_PCS_CTRL2_10GBR) {
442                 mode = XGBE_MODE_KR;
443         } else {
444                 if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
445                         mode = XGBE_MODE_KX_2500;
446                 else
447                         mode = XGBE_MODE_KX_1000;
448         }
449
450         return (mode);
451 }
452
453 static enum xgbe_mode
454 xgbe_phy_switch_mode(struct xgbe_prv_data *pdata)
455 {
456         struct xgbe_phy_data *phy_data = pdata->phy_data;
457         enum xgbe_mode mode;
458
459         /* If we are in KR switch to KX, and vice-versa */
460         if (xgbe_phy_cur_mode(pdata) == XGBE_MODE_KR) {
461                 if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
462                         mode = XGBE_MODE_KX_2500;
463                 else
464                         mode = XGBE_MODE_KX_1000;
465         } else {
466                 mode = XGBE_MODE_KR;
467         }
468
469         return (mode);
470 }
471
472 static enum xgbe_mode
473 xgbe_phy_get_mode(struct xgbe_prv_data *pdata, int speed)
474 {
475         struct xgbe_phy_data *phy_data = pdata->phy_data;
476
477         switch (speed) {
478         case SPEED_1000:
479                 return ((phy_data->speed_set == XGBE_SPEEDSET_1000_10000)
480                         ? XGBE_MODE_KX_1000 : XGBE_MODE_UNKNOWN);
481         case SPEED_2500:
482                 return ((phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
483                         ? XGBE_MODE_KX_2500 : XGBE_MODE_UNKNOWN);
484         case SPEED_10000:
485                 return (XGBE_MODE_KR);
486         default:
487                 return (XGBE_MODE_UNKNOWN);
488         }
489 }
490
491 static void
492 xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
493 {
494         switch (mode) {
495         case XGBE_MODE_KX_1000:
496                 xgbe_phy_kx_1000_mode(pdata);
497                 break;
498         case XGBE_MODE_KX_2500:
499                 xgbe_phy_kx_2500_mode(pdata);
500                 break;
501         case XGBE_MODE_KR:
502                 xgbe_phy_kr_mode(pdata);
503                 break;
504         default:
505                 break;
506         }
507 }
508
509 static void
510 xgbe_phy_get_type(struct xgbe_prv_data *pdata, struct ifmediareq * ifmr)
511 {
512
513         switch (pdata->phy.speed) {
514         case SPEED_10000:
515                 ifmr->ifm_active |= IFM_10G_KR;
516                 break;
517         case SPEED_2500:
518                 ifmr->ifm_active |= IFM_2500_KX;
519                 break;
520         case SPEED_1000:
521                 ifmr->ifm_active |= IFM_1000_KX;
522                 break;
523         default:
524                 ifmr->ifm_active |= IFM_OTHER;
525                 break;
526         }
527 }
528
529 static bool
530 xgbe_phy_check_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode, bool advert)
531 {
532
533         if (pdata->phy.autoneg == AUTONEG_ENABLE)
534                 return (advert);
535         else {
536                 enum xgbe_mode cur_mode;
537
538                 cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed);
539                 if (cur_mode == mode)
540                         return (true);
541         }
542
543         return (false);
544 }
545
546 static bool
547 xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
548 {
549
550         switch (mode) {
551         case XGBE_MODE_KX_1000:
552                 return (xgbe_phy_check_mode(pdata, mode,
553                     XGBE_ADV(&pdata->phy, 1000baseKX_Full)));
554         case XGBE_MODE_KX_2500:
555                 return (xgbe_phy_check_mode(pdata, mode,
556                     XGBE_ADV(&pdata->phy, 2500baseX_Full)));
557         case XGBE_MODE_KR:
558                 return (xgbe_phy_check_mode(pdata, mode,
559                     XGBE_ADV(&pdata->phy, 10000baseKR_Full)));
560         default:
561                 return (false);
562         }
563 }
564
565 static bool
566 xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
567 {
568         struct xgbe_phy_data *phy_data = pdata->phy_data;
569
570         switch (speed) {
571         case SPEED_1000:
572                 if (phy_data->speed_set != XGBE_SPEEDSET_1000_10000)
573                         return (false);
574                 return (true);
575         case SPEED_2500:
576                 if (phy_data->speed_set != XGBE_SPEEDSET_2500_10000)
577                         return (false);
578                 return (true);
579         case SPEED_10000:
580                 return (true);
581         default:
582                 return (false);
583         }
584 }
585
586 static int
587 xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
588 {
589         unsigned int reg;
590
591         *an_restart = 0;
592
593         /* Link status is latched low, so read once to clear
594          * and then read again to get current state
595          */
596         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
597         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
598
599         return ((reg & MDIO_STAT1_LSTATUS) ? 1 : 0);
600 }
601
602 static void
603 xgbe_phy_stop(struct xgbe_prv_data *pdata)
604 {
605         /* Nothing uniquely required for stop */
606 }
607
608 static int
609 xgbe_phy_start(struct xgbe_prv_data *pdata)
610 {
611         /* Nothing uniquely required for start */
612         return (0);
613 }
614
615 static int
616 xgbe_phy_reset(struct xgbe_prv_data *pdata)
617 {
618         unsigned int reg, count;
619
620         /* Perform a software reset of the PCS */
621         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
622         reg |= MDIO_CTRL1_RESET;
623         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
624
625         count = 50;
626         do {
627                 DELAY(20);
628                 reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
629         } while ((reg & MDIO_CTRL1_RESET) && --count);
630
631         if (reg & MDIO_CTRL1_RESET)
632                 return (-ETIMEDOUT);
633
634         return (0);
635 }
636
637 static void
638 xgbe_phy_exit(struct xgbe_prv_data *pdata)
639 {
640         /* Nothing uniquely required for exit */
641 }
642
643 static int
644 xgbe_phy_init(struct xgbe_prv_data *pdata)
645 {
646         struct xgbe_phy_data *phy_data;
647
648         phy_data = malloc(sizeof(*phy_data), M_AXGBE, M_WAITOK | M_ZERO);
649
650         /* Initialize supported features */
651         XGBE_ZERO_SUP(&pdata->phy);
652         XGBE_SET_SUP(&pdata->phy, Autoneg);
653         XGBE_SET_SUP(&pdata->phy, Pause);
654         XGBE_SET_SUP(&pdata->phy, Asym_Pause);
655         XGBE_SET_SUP(&pdata->phy, Backplane);
656         XGBE_SET_SUP(&pdata->phy, 10000baseKR_Full);
657         switch (phy_data->speed_set) {
658         case XGBE_SPEEDSET_1000_10000:
659                 XGBE_SET_SUP(&pdata->phy, 1000baseKX_Full);
660                 break;
661         case XGBE_SPEEDSET_2500_10000:
662                 XGBE_SET_SUP(&pdata->phy, 2500baseX_Full);
663                 break;
664         }
665
666         if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
667                 XGBE_SET_SUP(&pdata->phy, 10000baseR_FEC);
668
669         pdata->phy_data = phy_data;
670
671         return (0);
672 }
673
674 void
675 xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if)
676 {
677         struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
678
679         phy_impl->init                  = xgbe_phy_init;
680         phy_impl->exit                  = xgbe_phy_exit;
681
682         phy_impl->reset                 = xgbe_phy_reset;
683         phy_impl->start                 = xgbe_phy_start;
684         phy_impl->stop                  = xgbe_phy_stop;
685
686         phy_impl->link_status           = xgbe_phy_link_status;
687
688         phy_impl->valid_speed           = xgbe_phy_valid_speed;
689
690         phy_impl->use_mode              = xgbe_phy_use_mode;
691         phy_impl->set_mode              = xgbe_phy_set_mode;
692         phy_impl->get_mode              = xgbe_phy_get_mode;
693         phy_impl->switch_mode           = xgbe_phy_switch_mode;
694         phy_impl->cur_mode              = xgbe_phy_cur_mode;
695         phy_impl->get_type              = xgbe_phy_get_type;
696
697         phy_impl->an_mode               = xgbe_phy_an_mode;
698
699         phy_impl->an_config             = xgbe_phy_an_config;
700
701         phy_impl->an_advertising        = xgbe_phy_an_advertising;
702
703         phy_impl->an_outcome            = xgbe_phy_an_outcome;
704
705         phy_impl->kr_training_pre       = xgbe_phy_kr_training_pre;
706         phy_impl->kr_training_post      = xgbe_phy_kr_training_post;
707 }