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 | * |
9 | * Copyright (c) 2016 Advanced Micro Devices, Inc. |
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 | * Copyright (c) 2016 Advanced Micro Devices, Inc. |
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> |
119 | #include <linux/device.h> |
120 | #include <linux/property.h> |
121 | #include <linux/mdio.h> |
122 | #include <linux/phy.h> |
123 | |
124 | #include "xgbe.h" |
125 | #include "xgbe-common.h" |
126 | |
127 | #define XGBE_BLWC_PROPERTY "amd,serdes-blwc" |
128 | #define XGBE_CDR_RATE_PROPERTY "amd,serdes-cdr-rate" |
129 | #define XGBE_PQ_SKEW_PROPERTY "amd,serdes-pq-skew" |
130 | #define XGBE_TX_AMP_PROPERTY "amd,serdes-tx-amp" |
131 | #define XGBE_DFE_CFG_PROPERTY "amd,serdes-dfe-tap-config" |
132 | #define XGBE_DFE_ENA_PROPERTY "amd,serdes-dfe-tap-enable" |
133 | |
134 | /* Default SerDes settings */ |
135 | #define XGBE_SPEED_1000_BLWC 1 |
136 | #define XGBE_SPEED_1000_CDR 0x2 |
137 | #define XGBE_SPEED_1000_PLL 0x0 |
138 | #define XGBE_SPEED_1000_PQ 0xa |
139 | #define XGBE_SPEED_1000_RATE 0x3 |
140 | #define XGBE_SPEED_1000_TXAMP 0xf |
141 | #define XGBE_SPEED_1000_WORD 0x1 |
142 | #define XGBE_SPEED_1000_DFE_TAP_CONFIG 0x3 |
143 | #define XGBE_SPEED_1000_DFE_TAP_ENABLE 0x0 |
144 | |
145 | #define XGBE_SPEED_2500_BLWC 1 |
146 | #define XGBE_SPEED_2500_CDR 0x2 |
147 | #define XGBE_SPEED_2500_PLL 0x0 |
148 | #define XGBE_SPEED_2500_PQ 0xa |
149 | #define XGBE_SPEED_2500_RATE 0x1 |
150 | #define XGBE_SPEED_2500_TXAMP 0xf |
151 | #define XGBE_SPEED_2500_WORD 0x1 |
152 | #define XGBE_SPEED_2500_DFE_TAP_CONFIG 0x3 |
153 | #define XGBE_SPEED_2500_DFE_TAP_ENABLE 0x0 |
154 | |
155 | #define XGBE_SPEED_10000_BLWC 0 |
156 | #define XGBE_SPEED_10000_CDR 0x7 |
157 | #define XGBE_SPEED_10000_PLL 0x1 |
158 | #define XGBE_SPEED_10000_PQ 0x12 |
159 | #define XGBE_SPEED_10000_RATE 0x0 |
160 | #define XGBE_SPEED_10000_TXAMP 0xa |
161 | #define XGBE_SPEED_10000_WORD 0x7 |
162 | #define XGBE_SPEED_10000_DFE_TAP_CONFIG 0x1 |
163 | #define XGBE_SPEED_10000_DFE_TAP_ENABLE 0x7f |
164 | |
165 | /* Rate-change complete wait/retry count */ |
166 | #define XGBE_RATECHANGE_COUNT 500 |
167 | |
168 | static const u32 xgbe_phy_blwc[] = { |
169 | XGBE_SPEED_1000_BLWC, |
170 | XGBE_SPEED_2500_BLWC, |
171 | XGBE_SPEED_10000_BLWC, |
172 | }; |
173 | |
174 | static const u32 xgbe_phy_cdr_rate[] = { |
175 | XGBE_SPEED_1000_CDR, |
176 | XGBE_SPEED_2500_CDR, |
177 | XGBE_SPEED_10000_CDR, |
178 | }; |
179 | |
180 | static const u32 xgbe_phy_pq_skew[] = { |
181 | XGBE_SPEED_1000_PQ, |
182 | XGBE_SPEED_2500_PQ, |
183 | XGBE_SPEED_10000_PQ, |
184 | }; |
185 | |
186 | static const u32 xgbe_phy_tx_amp[] = { |
187 | XGBE_SPEED_1000_TXAMP, |
188 | XGBE_SPEED_2500_TXAMP, |
189 | XGBE_SPEED_10000_TXAMP, |
190 | }; |
191 | |
192 | static const u32 xgbe_phy_dfe_tap_cfg[] = { |
193 | XGBE_SPEED_1000_DFE_TAP_CONFIG, |
194 | XGBE_SPEED_2500_DFE_TAP_CONFIG, |
195 | XGBE_SPEED_10000_DFE_TAP_CONFIG, |
196 | }; |
197 | |
198 | static const u32 xgbe_phy_dfe_tap_ena[] = { |
199 | XGBE_SPEED_1000_DFE_TAP_ENABLE, |
200 | XGBE_SPEED_2500_DFE_TAP_ENABLE, |
201 | XGBE_SPEED_10000_DFE_TAP_ENABLE, |
202 | }; |
203 | |
204 | struct xgbe_phy_data { |
205 | /* 1000/10000 vs 2500/10000 indicator */ |
206 | unsigned int speed_set; |
207 | |
208 | /* SerDes UEFI configurable settings. |
209 | * Switching between modes/speeds requires new values for some |
210 | * SerDes settings. The values can be supplied as device |
211 | * properties in array format. The first array entry is for |
212 | * 1GbE, second for 2.5GbE and third for 10GbE |
213 | */ |
214 | u32 blwc[XGBE_SPEEDS]; |
215 | u32 cdr_rate[XGBE_SPEEDS]; |
216 | u32 pq_skew[XGBE_SPEEDS]; |
217 | u32 tx_amp[XGBE_SPEEDS]; |
218 | u32 dfe_tap_cfg[XGBE_SPEEDS]; |
219 | u32 dfe_tap_ena[XGBE_SPEEDS]; |
220 | }; |
221 | |
222 | static void xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata) |
223 | { |
224 | XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1); |
225 | } |
226 | |
227 | static void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata) |
228 | { |
229 | XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0); |
230 | } |
231 | |
232 | static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata) |
233 | { |
234 | struct ethtool_link_ksettings *lks = &pdata->phy.lks; |
235 | struct xgbe_phy_data *phy_data = pdata->phy_data; |
236 | enum xgbe_mode mode; |
237 | unsigned int ad_reg, lp_reg; |
238 | |
239 | XGBE_SET_LP_ADV(lks, Autoneg); |
240 | XGBE_SET_LP_ADV(lks, Backplane); |
241 | |
242 | /* Compare Advertisement and Link Partner register 1 */ |
243 | ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE); |
244 | lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA); |
245 | if (lp_reg & 0x400) |
246 | XGBE_SET_LP_ADV(lks, Pause); |
247 | if (lp_reg & 0x800) |
248 | XGBE_SET_LP_ADV(lks, Asym_Pause); |
249 | |
250 | if (pdata->phy.pause_autoneg) { |
251 | /* Set flow control based on auto-negotiation result */ |
252 | pdata->phy.tx_pause = 0; |
253 | pdata->phy.rx_pause = 0; |
254 | |
255 | if (ad_reg & lp_reg & 0x400) { |
256 | pdata->phy.tx_pause = 1; |
257 | pdata->phy.rx_pause = 1; |
258 | } else if (ad_reg & lp_reg & 0x800) { |
259 | if (ad_reg & 0x400) |
260 | pdata->phy.rx_pause = 1; |
261 | else if (lp_reg & 0x400) |
262 | pdata->phy.tx_pause = 1; |
263 | } |
264 | } |
265 | |
266 | /* Compare Advertisement and Link Partner register 2 */ |
267 | ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1); |
268 | lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1); |
269 | if (lp_reg & 0x80) |
270 | XGBE_SET_LP_ADV(lks, 10000baseKR_Full); |
271 | if (lp_reg & 0x20) { |
272 | if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000) |
273 | XGBE_SET_LP_ADV(lks, 2500baseX_Full); |
274 | else |
275 | XGBE_SET_LP_ADV(lks, 1000baseKX_Full); |
276 | } |
277 | |
278 | ad_reg &= lp_reg; |
279 | if (ad_reg & 0x80) { |
280 | mode = XGBE_MODE_KR; |
281 | } else if (ad_reg & 0x20) { |
282 | if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000) |
283 | mode = XGBE_MODE_KX_2500; |
284 | else |
285 | mode = XGBE_MODE_KX_1000; |
286 | } else { |
287 | mode = XGBE_MODE_UNKNOWN; |
288 | } |
289 | |
290 | /* Compare Advertisement and Link Partner register 3 */ |
291 | ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2); |
292 | lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2); |
293 | if (lp_reg & 0xc000) |
294 | XGBE_SET_LP_ADV(lks, 10000baseR_FEC); |
295 | |
296 | return mode; |
297 | } |
298 | |
299 | static void xgbe_phy_an_advertising(struct xgbe_prv_data *pdata, |
300 | struct ethtool_link_ksettings *dlks) |
301 | { |
302 | struct ethtool_link_ksettings *slks = &pdata->phy.lks; |
303 | |
304 | XGBE_LM_COPY(dlks, advertising, slks, advertising); |
305 | } |
306 | |
307 | static int xgbe_phy_an_config(struct xgbe_prv_data *pdata) |
308 | { |
309 | /* Nothing uniquely required for an configuration */ |
310 | return 0; |
311 | } |
312 | |
313 | static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata) |
314 | { |
315 | return XGBE_AN_MODE_CL73; |
316 | } |
317 | |
318 | static void xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata) |
319 | { |
320 | unsigned int reg; |
321 | |
322 | reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); |
323 | |
324 | reg |= MDIO_CTRL1_LPOWER; |
325 | XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); |
326 | |
327 | usleep_range(min: 75, max: 100); |
328 | |
329 | reg &= ~MDIO_CTRL1_LPOWER; |
330 | XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); |
331 | } |
332 | |
333 | static void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata) |
334 | { |
335 | /* Assert Rx and Tx ratechange */ |
336 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1); |
337 | } |
338 | |
339 | static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata) |
340 | { |
341 | unsigned int wait; |
342 | u16 status; |
343 | |
344 | /* Release Rx and Tx ratechange */ |
345 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0); |
346 | |
347 | /* Wait for Rx and Tx ready */ |
348 | wait = XGBE_RATECHANGE_COUNT; |
349 | while (wait--) { |
350 | usleep_range(min: 50, max: 75); |
351 | |
352 | status = XSIR0_IOREAD(pdata, SIR0_STATUS); |
353 | if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) && |
354 | XSIR_GET_BITS(status, SIR0_STATUS, TX_READY)) |
355 | goto rx_reset; |
356 | } |
357 | |
358 | netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n" , |
359 | status); |
360 | |
361 | rx_reset: |
362 | /* Perform Rx reset for the DFE changes */ |
363 | XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0); |
364 | XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1); |
365 | } |
366 | |
367 | static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata) |
368 | { |
369 | struct xgbe_phy_data *phy_data = pdata->phy_data; |
370 | unsigned int reg; |
371 | |
372 | /* Set PCS to KR/10G speed */ |
373 | reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); |
374 | reg &= ~MDIO_PCS_CTRL2_TYPE; |
375 | reg |= MDIO_PCS_CTRL2_10GBR; |
376 | XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg); |
377 | |
378 | reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); |
379 | reg &= ~MDIO_CTRL1_SPEEDSEL; |
380 | reg |= MDIO_CTRL1_SPEED10G; |
381 | XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); |
382 | |
383 | xgbe_phy_pcs_power_cycle(pdata); |
384 | |
385 | /* Set SerDes to 10G speed */ |
386 | xgbe_phy_start_ratechange(pdata); |
387 | |
388 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE); |
389 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD); |
390 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL); |
391 | |
392 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE, |
393 | phy_data->cdr_rate[XGBE_SPEED_10000]); |
394 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP, |
395 | phy_data->tx_amp[XGBE_SPEED_10000]); |
396 | XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA, |
397 | phy_data->blwc[XGBE_SPEED_10000]); |
398 | XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG, |
399 | phy_data->pq_skew[XGBE_SPEED_10000]); |
400 | XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG, |
401 | phy_data->dfe_tap_cfg[XGBE_SPEED_10000]); |
402 | XRXTX_IOWRITE(pdata, RXTX_REG22, |
403 | phy_data->dfe_tap_ena[XGBE_SPEED_10000]); |
404 | |
405 | xgbe_phy_complete_ratechange(pdata); |
406 | |
407 | netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n" ); |
408 | } |
409 | |
410 | static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata) |
411 | { |
412 | struct xgbe_phy_data *phy_data = pdata->phy_data; |
413 | unsigned int reg; |
414 | |
415 | /* Set PCS to KX/1G speed */ |
416 | reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); |
417 | reg &= ~MDIO_PCS_CTRL2_TYPE; |
418 | reg |= MDIO_PCS_CTRL2_10GBX; |
419 | XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg); |
420 | |
421 | reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); |
422 | reg &= ~MDIO_CTRL1_SPEEDSEL; |
423 | reg |= MDIO_CTRL1_SPEED1G; |
424 | XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); |
425 | |
426 | xgbe_phy_pcs_power_cycle(pdata); |
427 | |
428 | /* Set SerDes to 2.5G speed */ |
429 | xgbe_phy_start_ratechange(pdata); |
430 | |
431 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE); |
432 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD); |
433 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL); |
434 | |
435 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE, |
436 | phy_data->cdr_rate[XGBE_SPEED_2500]); |
437 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP, |
438 | phy_data->tx_amp[XGBE_SPEED_2500]); |
439 | XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA, |
440 | phy_data->blwc[XGBE_SPEED_2500]); |
441 | XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG, |
442 | phy_data->pq_skew[XGBE_SPEED_2500]); |
443 | XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG, |
444 | phy_data->dfe_tap_cfg[XGBE_SPEED_2500]); |
445 | XRXTX_IOWRITE(pdata, RXTX_REG22, |
446 | phy_data->dfe_tap_ena[XGBE_SPEED_2500]); |
447 | |
448 | xgbe_phy_complete_ratechange(pdata); |
449 | |
450 | netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n" ); |
451 | } |
452 | |
453 | static void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata) |
454 | { |
455 | struct xgbe_phy_data *phy_data = pdata->phy_data; |
456 | unsigned int reg; |
457 | |
458 | /* Set PCS to KX/1G speed */ |
459 | reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); |
460 | reg &= ~MDIO_PCS_CTRL2_TYPE; |
461 | reg |= MDIO_PCS_CTRL2_10GBX; |
462 | XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg); |
463 | |
464 | reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); |
465 | reg &= ~MDIO_CTRL1_SPEEDSEL; |
466 | reg |= MDIO_CTRL1_SPEED1G; |
467 | XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); |
468 | |
469 | xgbe_phy_pcs_power_cycle(pdata); |
470 | |
471 | /* Set SerDes to 1G speed */ |
472 | xgbe_phy_start_ratechange(pdata); |
473 | |
474 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE); |
475 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD); |
476 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL); |
477 | |
478 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE, |
479 | phy_data->cdr_rate[XGBE_SPEED_1000]); |
480 | XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP, |
481 | phy_data->tx_amp[XGBE_SPEED_1000]); |
482 | XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA, |
483 | phy_data->blwc[XGBE_SPEED_1000]); |
484 | XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG, |
485 | phy_data->pq_skew[XGBE_SPEED_1000]); |
486 | XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG, |
487 | phy_data->dfe_tap_cfg[XGBE_SPEED_1000]); |
488 | XRXTX_IOWRITE(pdata, RXTX_REG22, |
489 | phy_data->dfe_tap_ena[XGBE_SPEED_1000]); |
490 | |
491 | xgbe_phy_complete_ratechange(pdata); |
492 | |
493 | netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n" ); |
494 | } |
495 | |
496 | static enum xgbe_mode xgbe_phy_cur_mode(struct xgbe_prv_data *pdata) |
497 | { |
498 | struct xgbe_phy_data *phy_data = pdata->phy_data; |
499 | enum xgbe_mode mode; |
500 | unsigned int reg; |
501 | |
502 | reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2); |
503 | reg &= MDIO_PCS_CTRL2_TYPE; |
504 | |
505 | if (reg == MDIO_PCS_CTRL2_10GBR) { |
506 | mode = XGBE_MODE_KR; |
507 | } else { |
508 | if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000) |
509 | mode = XGBE_MODE_KX_2500; |
510 | else |
511 | mode = XGBE_MODE_KX_1000; |
512 | } |
513 | |
514 | return mode; |
515 | } |
516 | |
517 | static enum xgbe_mode xgbe_phy_switch_mode(struct xgbe_prv_data *pdata) |
518 | { |
519 | struct xgbe_phy_data *phy_data = pdata->phy_data; |
520 | enum xgbe_mode mode; |
521 | |
522 | /* If we are in KR switch to KX, and vice-versa */ |
523 | if (xgbe_phy_cur_mode(pdata) == XGBE_MODE_KR) { |
524 | if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000) |
525 | mode = XGBE_MODE_KX_2500; |
526 | else |
527 | mode = XGBE_MODE_KX_1000; |
528 | } else { |
529 | mode = XGBE_MODE_KR; |
530 | } |
531 | |
532 | return mode; |
533 | } |
534 | |
535 | static enum xgbe_mode xgbe_phy_get_mode(struct xgbe_prv_data *pdata, |
536 | int speed) |
537 | { |
538 | struct xgbe_phy_data *phy_data = pdata->phy_data; |
539 | |
540 | switch (speed) { |
541 | case SPEED_1000: |
542 | return (phy_data->speed_set == XGBE_SPEEDSET_1000_10000) |
543 | ? XGBE_MODE_KX_1000 : XGBE_MODE_UNKNOWN; |
544 | case SPEED_2500: |
545 | return (phy_data->speed_set == XGBE_SPEEDSET_2500_10000) |
546 | ? XGBE_MODE_KX_2500 : XGBE_MODE_UNKNOWN; |
547 | case SPEED_10000: |
548 | return XGBE_MODE_KR; |
549 | default: |
550 | return XGBE_MODE_UNKNOWN; |
551 | } |
552 | } |
553 | |
554 | static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode) |
555 | { |
556 | switch (mode) { |
557 | case XGBE_MODE_KX_1000: |
558 | xgbe_phy_kx_1000_mode(pdata); |
559 | break; |
560 | case XGBE_MODE_KX_2500: |
561 | xgbe_phy_kx_2500_mode(pdata); |
562 | break; |
563 | case XGBE_MODE_KR: |
564 | xgbe_phy_kr_mode(pdata); |
565 | break; |
566 | default: |
567 | break; |
568 | } |
569 | } |
570 | |
571 | static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata, |
572 | enum xgbe_mode mode, bool advert) |
573 | { |
574 | if (pdata->phy.autoneg == AUTONEG_ENABLE) { |
575 | return advert; |
576 | } else { |
577 | enum xgbe_mode cur_mode; |
578 | |
579 | cur_mode = xgbe_phy_get_mode(pdata, speed: pdata->phy.speed); |
580 | if (cur_mode == mode) |
581 | return true; |
582 | } |
583 | |
584 | return false; |
585 | } |
586 | |
587 | static bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode) |
588 | { |
589 | struct ethtool_link_ksettings *lks = &pdata->phy.lks; |
590 | |
591 | switch (mode) { |
592 | case XGBE_MODE_KX_1000: |
593 | return xgbe_phy_check_mode(pdata, mode, |
594 | XGBE_ADV(lks, 1000baseKX_Full)); |
595 | case XGBE_MODE_KX_2500: |
596 | return xgbe_phy_check_mode(pdata, mode, |
597 | XGBE_ADV(lks, 2500baseX_Full)); |
598 | case XGBE_MODE_KR: |
599 | return xgbe_phy_check_mode(pdata, mode, |
600 | XGBE_ADV(lks, 10000baseKR_Full)); |
601 | default: |
602 | return false; |
603 | } |
604 | } |
605 | |
606 | static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed) |
607 | { |
608 | struct xgbe_phy_data *phy_data = pdata->phy_data; |
609 | |
610 | switch (speed) { |
611 | case SPEED_1000: |
612 | if (phy_data->speed_set != XGBE_SPEEDSET_1000_10000) |
613 | return false; |
614 | return true; |
615 | case SPEED_2500: |
616 | if (phy_data->speed_set != XGBE_SPEEDSET_2500_10000) |
617 | return false; |
618 | return true; |
619 | case SPEED_10000: |
620 | return true; |
621 | default: |
622 | return false; |
623 | } |
624 | } |
625 | |
626 | static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart) |
627 | { |
628 | unsigned int reg; |
629 | |
630 | *an_restart = 0; |
631 | |
632 | /* Link status is latched low, so read once to clear |
633 | * and then read again to get current state |
634 | */ |
635 | reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); |
636 | reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); |
637 | |
638 | return (reg & MDIO_STAT1_LSTATUS) ? 1 : 0; |
639 | } |
640 | |
641 | static void xgbe_phy_stop(struct xgbe_prv_data *pdata) |
642 | { |
643 | /* Nothing uniquely required for stop */ |
644 | } |
645 | |
646 | static int xgbe_phy_start(struct xgbe_prv_data *pdata) |
647 | { |
648 | /* Nothing uniquely required for start */ |
649 | return 0; |
650 | } |
651 | |
652 | static int xgbe_phy_reset(struct xgbe_prv_data *pdata) |
653 | { |
654 | unsigned int reg, count; |
655 | |
656 | /* Perform a software reset of the PCS */ |
657 | reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); |
658 | reg |= MDIO_CTRL1_RESET; |
659 | XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg); |
660 | |
661 | count = 50; |
662 | do { |
663 | msleep(msecs: 20); |
664 | reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1); |
665 | } while ((reg & MDIO_CTRL1_RESET) && --count); |
666 | |
667 | if (reg & MDIO_CTRL1_RESET) |
668 | return -ETIMEDOUT; |
669 | |
670 | return 0; |
671 | } |
672 | |
673 | static void xgbe_phy_exit(struct xgbe_prv_data *pdata) |
674 | { |
675 | /* Nothing uniquely required for exit */ |
676 | } |
677 | |
678 | static int xgbe_phy_init(struct xgbe_prv_data *pdata) |
679 | { |
680 | struct ethtool_link_ksettings *lks = &pdata->phy.lks; |
681 | struct xgbe_phy_data *phy_data; |
682 | int ret; |
683 | |
684 | phy_data = devm_kzalloc(dev: pdata->dev, size: sizeof(*phy_data), GFP_KERNEL); |
685 | if (!phy_data) |
686 | return -ENOMEM; |
687 | |
688 | /* Retrieve the PHY speedset */ |
689 | ret = device_property_read_u32(dev: pdata->phy_dev, XGBE_SPEEDSET_PROPERTY, |
690 | val: &phy_data->speed_set); |
691 | if (ret) { |
692 | dev_err(pdata->dev, "invalid %s property\n" , |
693 | XGBE_SPEEDSET_PROPERTY); |
694 | return ret; |
695 | } |
696 | |
697 | switch (phy_data->speed_set) { |
698 | case XGBE_SPEEDSET_1000_10000: |
699 | case XGBE_SPEEDSET_2500_10000: |
700 | break; |
701 | default: |
702 | dev_err(pdata->dev, "invalid %s property\n" , |
703 | XGBE_SPEEDSET_PROPERTY); |
704 | return -EINVAL; |
705 | } |
706 | |
707 | /* Retrieve the PHY configuration properties */ |
708 | if (device_property_present(dev: pdata->phy_dev, XGBE_BLWC_PROPERTY)) { |
709 | ret = device_property_read_u32_array(dev: pdata->phy_dev, |
710 | XGBE_BLWC_PROPERTY, |
711 | val: phy_data->blwc, |
712 | nval: XGBE_SPEEDS); |
713 | if (ret) { |
714 | dev_err(pdata->dev, "invalid %s property\n" , |
715 | XGBE_BLWC_PROPERTY); |
716 | return ret; |
717 | } |
718 | } else { |
719 | memcpy(phy_data->blwc, xgbe_phy_blwc, |
720 | sizeof(phy_data->blwc)); |
721 | } |
722 | |
723 | if (device_property_present(dev: pdata->phy_dev, XGBE_CDR_RATE_PROPERTY)) { |
724 | ret = device_property_read_u32_array(dev: pdata->phy_dev, |
725 | XGBE_CDR_RATE_PROPERTY, |
726 | val: phy_data->cdr_rate, |
727 | nval: XGBE_SPEEDS); |
728 | if (ret) { |
729 | dev_err(pdata->dev, "invalid %s property\n" , |
730 | XGBE_CDR_RATE_PROPERTY); |
731 | return ret; |
732 | } |
733 | } else { |
734 | memcpy(phy_data->cdr_rate, xgbe_phy_cdr_rate, |
735 | sizeof(phy_data->cdr_rate)); |
736 | } |
737 | |
738 | if (device_property_present(dev: pdata->phy_dev, XGBE_PQ_SKEW_PROPERTY)) { |
739 | ret = device_property_read_u32_array(dev: pdata->phy_dev, |
740 | XGBE_PQ_SKEW_PROPERTY, |
741 | val: phy_data->pq_skew, |
742 | nval: XGBE_SPEEDS); |
743 | if (ret) { |
744 | dev_err(pdata->dev, "invalid %s property\n" , |
745 | XGBE_PQ_SKEW_PROPERTY); |
746 | return ret; |
747 | } |
748 | } else { |
749 | memcpy(phy_data->pq_skew, xgbe_phy_pq_skew, |
750 | sizeof(phy_data->pq_skew)); |
751 | } |
752 | |
753 | if (device_property_present(dev: pdata->phy_dev, XGBE_TX_AMP_PROPERTY)) { |
754 | ret = device_property_read_u32_array(dev: pdata->phy_dev, |
755 | XGBE_TX_AMP_PROPERTY, |
756 | val: phy_data->tx_amp, |
757 | nval: XGBE_SPEEDS); |
758 | if (ret) { |
759 | dev_err(pdata->dev, "invalid %s property\n" , |
760 | XGBE_TX_AMP_PROPERTY); |
761 | return ret; |
762 | } |
763 | } else { |
764 | memcpy(phy_data->tx_amp, xgbe_phy_tx_amp, |
765 | sizeof(phy_data->tx_amp)); |
766 | } |
767 | |
768 | if (device_property_present(dev: pdata->phy_dev, XGBE_DFE_CFG_PROPERTY)) { |
769 | ret = device_property_read_u32_array(dev: pdata->phy_dev, |
770 | XGBE_DFE_CFG_PROPERTY, |
771 | val: phy_data->dfe_tap_cfg, |
772 | nval: XGBE_SPEEDS); |
773 | if (ret) { |
774 | dev_err(pdata->dev, "invalid %s property\n" , |
775 | XGBE_DFE_CFG_PROPERTY); |
776 | return ret; |
777 | } |
778 | } else { |
779 | memcpy(phy_data->dfe_tap_cfg, xgbe_phy_dfe_tap_cfg, |
780 | sizeof(phy_data->dfe_tap_cfg)); |
781 | } |
782 | |
783 | if (device_property_present(dev: pdata->phy_dev, XGBE_DFE_ENA_PROPERTY)) { |
784 | ret = device_property_read_u32_array(dev: pdata->phy_dev, |
785 | XGBE_DFE_ENA_PROPERTY, |
786 | val: phy_data->dfe_tap_ena, |
787 | nval: XGBE_SPEEDS); |
788 | if (ret) { |
789 | dev_err(pdata->dev, "invalid %s property\n" , |
790 | XGBE_DFE_ENA_PROPERTY); |
791 | return ret; |
792 | } |
793 | } else { |
794 | memcpy(phy_data->dfe_tap_ena, xgbe_phy_dfe_tap_ena, |
795 | sizeof(phy_data->dfe_tap_ena)); |
796 | } |
797 | |
798 | /* Initialize supported features */ |
799 | XGBE_ZERO_SUP(lks); |
800 | XGBE_SET_SUP(lks, Autoneg); |
801 | XGBE_SET_SUP(lks, Pause); |
802 | XGBE_SET_SUP(lks, Asym_Pause); |
803 | XGBE_SET_SUP(lks, Backplane); |
804 | XGBE_SET_SUP(lks, 10000baseKR_Full); |
805 | switch (phy_data->speed_set) { |
806 | case XGBE_SPEEDSET_1000_10000: |
807 | XGBE_SET_SUP(lks, 1000baseKX_Full); |
808 | break; |
809 | case XGBE_SPEEDSET_2500_10000: |
810 | XGBE_SET_SUP(lks, 2500baseX_Full); |
811 | break; |
812 | } |
813 | |
814 | if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE) |
815 | XGBE_SET_SUP(lks, 10000baseR_FEC); |
816 | |
817 | pdata->phy_data = phy_data; |
818 | |
819 | return 0; |
820 | } |
821 | |
822 | void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if) |
823 | { |
824 | struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl; |
825 | |
826 | phy_impl->init = xgbe_phy_init; |
827 | phy_impl->exit = xgbe_phy_exit; |
828 | |
829 | phy_impl->reset = xgbe_phy_reset; |
830 | phy_impl->start = xgbe_phy_start; |
831 | phy_impl->stop = xgbe_phy_stop; |
832 | |
833 | phy_impl->link_status = xgbe_phy_link_status; |
834 | |
835 | phy_impl->valid_speed = xgbe_phy_valid_speed; |
836 | |
837 | phy_impl->use_mode = xgbe_phy_use_mode; |
838 | phy_impl->set_mode = xgbe_phy_set_mode; |
839 | phy_impl->get_mode = xgbe_phy_get_mode; |
840 | phy_impl->switch_mode = xgbe_phy_switch_mode; |
841 | phy_impl->cur_mode = xgbe_phy_cur_mode; |
842 | |
843 | phy_impl->an_mode = xgbe_phy_an_mode; |
844 | |
845 | phy_impl->an_config = xgbe_phy_an_config; |
846 | |
847 | phy_impl->an_advertising = xgbe_phy_an_advertising; |
848 | |
849 | phy_impl->an_outcome = xgbe_phy_an_outcome; |
850 | |
851 | phy_impl->kr_training_pre = xgbe_phy_kr_training_pre; |
852 | phy_impl->kr_training_post = xgbe_phy_kr_training_post; |
853 | } |
854 | |